无法让 double.TryParse 在 Linq 表达式树中工作
Posted
技术标签:
【中文标题】无法让 double.TryParse 在 Linq 表达式树中工作【英文标题】:Unable to get double.TryParse to work in Linq Expression Tree 【发布时间】:2015-07-10 21:49:48 【问题描述】:我正在尝试使用 Linq 表达式为 IQueryable 数据源创建动态 where 子句。我无法让 TryParse 函数在其中一个表达式中工作。这是我想要做的:
IQueryable<trial_global> globalTrials = _trialsRepository.GlobalDataFiltered(filterId).AsQueryable();
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Static;
MethodInfo tryParseMethod = typeof(double).GetMethod("TryParse", bindingFlags, null, new Type[] typeof(string), typeof(double).MakeByRefType() , null);
Expression tempN = Expression.Parameter(typeof(double), "tempN");
Expression left = Expression.Call(tryParseMethod, new[] metricReference, tempN );
Expression right = Expression.Constant(true);
Expression predicateBody = Expression.Equal(left, right);
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] globalTrials.ElementType ,
globalTrials.Expression,
Expression.Lambda<Func<trial_global, bool>>(predicateBody, new ParameterExpression[] pe )
);
var results = globalTrials.Provider.CreateQuery<trial_global>(whereCallExpression);
在results
被分配之前一切正常,但出现以下错误:
variable 'tempN' of type 'System.Double' referenced from scope '', but it is not defined
我在这里缺少什么?我怀疑这与 double.TryParse 函数中的第二个参数是 out
参数有关。
更新:
我通过创建一个执行 TryParse 的静态函数并从 Expression 调用此静态函数来解决此问题:
public static bool IsStringNumeric(string checkStr)
double num = 0;
return double.TryParse(checkStr, out num);
public IQueryable<trial_global> GetTrials(IQueryable<trial_global> globalTrials, Metric metric)
ParameterExpression pe = Expression.Parameter(typeof(trial_global), "trial_global");
MemberExpression metricReference = Expression.Property(pe, metric.metric_name);
Expression predicateBody = Expression.Call(typeof(GlobalTrialsRepository).GetMethod("IsStringNumeric", new Type[] typeof(string) ), metricReference);
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] globalTrials.ElementType ,
globalTrials.Expression,
Expression.Lambda<Func<trial_global, bool>>(predicateBody, new ParameterExpression[] pe )
);
return globalTrials.Provider.CreateQuery<trial_global>(whereCallExpression);
这种方法可以吗?有没有人觉得这样做有什么坏处?
【问题讨论】:
如果你把谓词写成 lambda 表达式,它会是什么样子? 不需要生成x == true
。
另外,很少有 LINQ 提供者会处理 TryParse()
。
@MarcinJuraszek 这是我在double number; var res = globalTrials.Where(a => double.TryParse(a.Column1, out number));
之前使用的lambda 表达式当我将res
放入手表时,我在expression
下看到以下argument
:a => TryParse(a.Subjects_Per_Month, value(Application.Services.TrialGridSourceService+<>c__DisplayClass2).number)
【参考方案1】:
Tryparse 使用 out 参数进行检查。使用 tryparse 创建一个扩展方法,然后从 linq 调用扩展方法
【讨论】:
他可以创建表达式,但它不会与几乎任何提供者一起运行。 什么提供商理解 double.TryParse 反正? 对不起,虽然他想要一个函数来验证常规 linq 语句【参考方案2】:Linq 查询会延迟到对其调用 ToXXXX() 为止。因此,您可以将 Where 语句定义为 Linq 方法链,然后只需调用 .ToList 或其他任何方法来获取值。
【讨论】:
如果我理解正确你是说我应该做类似var res = _datasource.Where(a => a.Col1 == 'xyz').ToList()
的事情我不能这样做的原因是我想查询的列 (Col1
) 事先不知道.它会动态出现,因此需要创建动态表达式。以上是关于无法让 double.TryParse 在 Linq 表达式树中工作的主要内容,如果未能解决你的问题,请参考以下文章
Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?
asp.net 怎么让用户在文本框里填入的是数字和带有小数点? 正则也行!