无法让 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 =&gt; double.TryParse(a.Column1, out number)); 之前使用的lambda 表达式当我将res 放入手表时,我在expression 下看到以下argumenta =&gt; TryParse(a.Subjects_Per_Month, value(Application.Services.TrialGridSourceService+&lt;&gt;c__DisplayClass2).number) 【参考方案1】:

Tryparse 使用 out 参数进行检查。使用 tryparse 创建一个扩展方法,然后从 linq 调用扩展方法

【讨论】:

他可以创建表达式,但它不会与几乎任何提供者一起运行。 什么提供​​商理解 double.TryParse 反正? 对不起,虽然他想要一个函数来验证常规 linq 语句【参考方案2】:

Linq 查询会延迟到对其调用 ToXXXX() 为止。因此,您可以将 Where 语句定义为 Linq 方法链,然后只需调用 .ToList 或其他任何方法来获取值。

【讨论】:

如果我理解正确你是说我应该做类似var res = _datasource.Where(a =&gt; a.Col1 == 'xyz').ToList() 的事情我不能这样做的原因是我想查询的列 (Col1) 事先不知道.它会动态出现,因此需要创建动态表达式。

以上是关于无法让 double.TryParse 在 Linq 表达式树中工作的主要内容,如果未能解决你的问题,请参考以下文章

Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?

asp.net 怎么让用户在文本框里填入的是数字和带有小数点? 正则也行!

TryParse 适用于 var 但不适用于 C# 中的对象?

属性或索引器不能作为 out 或 ref 参数传递

TryCast 加倍?

将金额字符串解析为数字