我正在尝试在 C# 中创建一个表达式树来动态表示以下嵌套 lambda...
item => selectorList.Any(selector => terms.Any(sTerm => selector.Contains(sTerm))
地点:
- “item”是泛型类型 T
- 'selectorList' 的类型为 IEnumerable
>> - “terms”的类型为 IEnumerable
经过大量工作,我已经到达这里 - 但现在我正在努力把它做好。我缺少对嵌套时如何使用 ParameterExpression 作为解析值的一些基本理解。
public static Expression<Func<T, bool>> CreateWhereAnyContainsLambaExpression<T>(IEnumerable<string> terms, params Expression<Func<T, String>>[] selectorList)
{
// Create ParameterExpressions
ParameterExpression qi = Expression.Parameter(typeof(T), "qi");
ParameterExpression selector = Expression.Parameter(typeof(Expression<Func<T, String>>), "selector");
ParameterExpression sTerm = Expression.Parameter(typeof(string), "sTerm");
// Create ConstantExpressions
ConstantExpression termsConstant = Expression.Constant(terms);
ConstantExpression selectorListConstant = Expression.Constant(selectorList);
// Get MethodInfo
MethodInfo selectorListAny = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any").First(m => m.GetParameters().Count() == 2).MakeGenericMethod(typeof(Expression<Func<T, string>>));
MethodInfo termsAny = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any").First(m => m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string));
MethodInfo selectorContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
// Build the Expression from inside to out....
// selector.Contains(sTerm)
var expSelectorContains = Expression.Call(selector, selectorContains, sTerm);
// sTerm => ...expSelectorContains...
var sTermLambda = Expression.Lambda<Func<string, bool>>(expSelectorContains, sTerm);
// terms.Any(...sTermLambda...)
var expTermsAny = Expression.Call(termsConstant, termsAny, sTermLambda);
// selector => ...expTermsAny...
var selectorLambda = Expression.Lambda<Func<Expression<Func<T, string>>, bool>>(expTermsAny, selector);
// selectorList.Any(...selectorLambda...)
var expSelectorListAny = Expression.Call(selectorListConstant, selectorListAny, selectorLambda);
// item => ...expSelectorListAny...
var lambda = Expression.Lambda<Func<T, bool>>(expSelectorListAny, qi);
return lambda;
}
失败就在一线
// selector.Contains(sTerm)
var expSelectorContains = Expression.Call(selector, selectorContains, sTerm);
我在哪里得到异常
System.ArgumentException : Method 'Boolean Contains(System.String)' declared on type 'System.String' cannot be called with instance of type 'System.Linq.Expressions.Expression`1[System.Func`2[TestObject,System.String]]'
鉴于 sTerm 是树上的参数表达式,我如何将其解析的表示形式传递给 Contains 方法?
最佳答案
所以让我澄清一下我造成的困惑......
我正在构建 lambda selector.Contains(sTerm)
线路 var expSelectorContains = Expression.Call(selector, selectorContains, sTerm);
现在是selectorContains
预计将针对 string
的实例调用 MethodInfo 。然而我的selector
是 Expression<Func<T, String>>
类型的 ParameterExpression .
我只是将其与传入的选择器列表变量进行匹配,因为我应该将其与减少时解析的内容相匹配...这只是一个字符串。
所以解决办法是改变
ParameterExpression selector = Expression.Parameter(typeof(Expression<Func<T, String>>), "selector");
至
ParameterExpression selector = Expression.Parameter(typeof(string), "selector");
哦!我的错。衷心感谢您的建议。
关于c# - 与 C# 中的嵌套表达式树作斗争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66030266/