c# - 在 C# 中与嵌套表达式树作斗争
问题描述
我正在尝试在 C# 中创建一个表达式树来动态表示以下嵌套的 lambda ...
item => selectorList.Any(selector => terms.Any(sTerm => selector.Contains(sTerm))
在哪里:
- 'item' 是泛型类型 T
- 'selectorList' 的类型为 IEnumerable<Expression<Func<T,string>>>
- “条款”的类型为 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 方法?
解决方案
所以让我澄清一下我造成的混乱......我正在selector.Contains(sTerm)
用这条线构造 lambdavar expSelectorContains = Expression.Call(selector, selectorContains, sTerm);
现在selectorContains
MethodInfo 预计将针对string
. 但是 myselector
是 ParameterExpression 类型的Expression<Func<T, String>>
。
我只是将它与传入的 selectorList 变量相匹配,因为我应该将它与减少时解析的内容相匹配......这只是一个字符串。
所以解决办法是改变
ParameterExpression selector = Expression.Parameter(typeof(Expression<Func<T, String>>), "selector");
至
ParameterExpression selector = Expression.Parameter(typeof(string), "selector");
嗬!我的错。衷心感谢您的建议。
推荐阅读
- visual-studio-code - VSCode + 远程 WSL 某些功能不起作用
- python - 如何使用 python 从网站上抓取段落?
- java - 多态性实现对子字段的强制通用更改
- deep-learning - 连体网络的线性变换
- css - 如何使用 Sass '@use' 命令包含和使用外部变量文件?
- google-apps-script - 在谷歌应用脚本中创建一个条带令牌
- javascript - TypeError: undefined is not an object (evaluate '_reactNative.Stylesheet.create') in react native
- c# - C# Application Lync Function migrated to MS teams
- html - CSS-grid在网格中间插入列
- node.js - Heroku Dyno 莫名其妙地倒下了?