如何使用Any语句正确创建Expression?

时间:2019-06-09 18:45:14

标签: c# lambda expression-trees

我想问一下如何为以下内容正确创建表达式:

x => x.AnotherEntities.Any(y => y.AnotherProp == "something")

我检查了很多示例,并阅读了很多有关Expressions的信息,以了解为什么我会出错,但仍然一无所获。

目前我正在尝试:

source = MyFunction(x => x.AnotherEntities, y => y.AnotherProp, "something", source);
private IQueryable<MyEntity> MyFunction<T>(Expression<Func<MyEntity, List<T>>> prop,
    Expression<Func<T, string>> subProp,
    string value,
    IQueryable<MyEntity> source)
{
    var method = typeof(Enumerable)
        .GetMethods()
        .FirstOrDefault(method => method.Name == "Any" 
            && method.GetParameters().Count() == 2)
        .MakeGenericMethod(typeof(T));

    var expression = Expression.Equal(subProp.Body, Expression.Constant(value));
    var lambda = Expression.Lambda<Func<T, bool>>(expression, subProp.Parameters);

    return source.Where(Expression.Lambda<Func<MyEntity, bool>>
    (
        body: Expression.Call
        (
            null, method, lambda
        ),
        parameters: prop.Parameters
    ));
}
public class MyEntity {
    public List<AnotherEntity> AnotherEntities { get; set; }
}

public class AnotherEntity {
    public string AnotherProp { get; set; }
}

获取异常:

  

ArgumentException为调用方法'Boolean提供的参数数量不正确Any [AnotherEntity](System.Collections.Generic.IEnumerable`1 [WebApplication.Models.AnotherEntity],System.Func`2 [WebApplication.Models.AnotherEntity,System .Boolean])'
  参数名称:方​​法

1 个答案:

答案 0 :(得分:0)

(免责声明:我是有关图书馆的作者。)

我建议使用ExpressionTreeToString(可作为NuGet package使用):

以下代码:

Expression<Func<MyEntity, bool>> expr = x => x.AnotherEntities.Any(y => y.AnotherProp == "something");
Console.WriteLine(
    expr.ToString("Factory methods")
);

打印:

// using static System.Linq.Expressions.Expression

Lambda(
    Call(
        typeof(Enumerable).GetMethod("Any"),
        MakeMemberAccess(x,
            typeof(MyEntity).GetProperty("AnotherEntities")
        ),
        Lambda(
            Equal(
                MakeMemberAccess(y,
                    typeof(AnotherEntity).GetProperty("AnotherProp")
                ),
                Constant("something")
            ),
            var y = Parameter(
                typeof(AnotherEntity),
                "y"
            )
        )
    ),
    var x = Parameter(
        typeof(MyEntity),
        "x"
    )
)

表明在这种情况下,Call需要三个参数:

  1. 方法
  2. 作为方法的第一个参数传递的对象-AnotherEntities实例上MyEntity的成员访问权限
  3. lambda表达式

您没有传递第二个参数。