c# - 与 C# 中的嵌套表达式树作斗争

标签 c# lambda expression-trees

我正在尝试在 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 。然而我的selectorExpression<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/

相关文章:

c# - WPF中如何实现双向数据绑定(bind)?

c# - 在决定应该在哪里定义枚举和结构时,什么是好的做法?

c# - 如何确定我的程序集是否可以被 Mono、MonoTouch、MonoDroid 使用?

lambda - 方案定义/lambda 简写

python - 使用 lambda 从字典列表中删除字典元素

java - 表达式树类中的递归evaluate()

c# - 将 JavaScript 正则表达式转换为 C#

c++ - 将捕获 lambda 作为函数指针传递

c# - 如何创建 LINQ 表达式树以选择匿名类型

c# - 如何获取使用局部变量的 ConstantExpression 的值?