【发布时间】: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)
标签: c# linq reflection lambda expression-trees