Как правильно создать выражение с любым оператором? - PullRequest
1 голос
/ 09 июня 2019

Я хотел спросить, как правильно создать выражение для:

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

Я проверил много примеров и прочитал много информации о выражениях, чтобы понять, почему я получаю ошибки, но все женичего такого.

В настоящее время я пытаюсь:

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 голосов
/ 26 июня 2019

(Отказ от ответственности: я являюсь автором рассматриваемой библиотеки.)

Я бы предложил использовать ExpressionTreeToString , доступный как пакет NuGet :

Следующий код:

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. method
  2. объект, который передается в качестве первого параметра метода - доступ к элементу AnotherEntities в экземпляре MyEntity
  3. лямбда-выражения

Вы не передаете второй аргумент.

...