Создание лямбда-выражений с помощью Contains на NetCore - PullRequest
0 голосов
/ 05 мая 2020

Хорошие сотрудники affertoon.

У меня возникла проблема, когда я попытался построить лямбда-выражение с помощью Expression.Builder, код выдает ошибку.

Скажите: «Метод Stati c требует нулевой экземпляр, нестатический c метод требует ненулевого экземпляра. ".

Я уже успешно использую простые выражения, например:

IQueryable<PersonTestModel> expected = data.Where(x => x.IsActive);


PersonTestModel expected = data.FirstOrDefault(x => x.Id != 3);


IQueryable<PersonTestModel> expected = data.Where(x => x.FirstName.StartsWith("a", StringComparison.InvariantCultureIgnoreCase));


IQueryable<PersonTestModel> expected = data.Where(x => x.Balance > averageBalance);

, но я не могу построить это выражение

var dataFilter = new HashSet<int> { 2 };
IQueryable<PersonTestModel> data = await PersonFaker.GetFakeSimpleData(60);

//this is expression i will try
Expression<Func<PersonTestModel, bool>> func = x => dataFilter.Contains(x.UserId);
var expected = data.Where(func);

Это мой код для построения выражений commos:

private static Expression GetExpression<T>(ParameterExpression parameter, QueryFilter queryFilter)
        {
            MemberExpression member = Expression.Property(parameter, queryFilter.PropertyName);
            ConstantExpression constant = GetConstant(member.Type, queryFilter.Value);

            switch (queryFilter.Operator)
            {
                case Operator.Equals:
                    return Expression.Equal(member, constant);
                case Operator.NotEqual:
                    return Expression.NotEqual(member, constant);
                case Operator.Contains:
                case Operator.StartsWith:
                case Operator.EndsWith:
                    {
                        constant = GetConstant(member.Type, queryFilter.Value.ToUpper());
                        return Expression.Call(Expression.Call(member, "ToUpper", null), queryFilter.Operator.ToString(), null, constant);
                    }
                case Operator.GreaterThan:
                    return Expression.GreaterThan(member, constant);
                case Operator.GreaterOrEqualThan:
                    return Expression.GreaterThanOrEqual(member, constant);
                case Operator.LessThan:
                    return Expression.LessThan(member, constant);
                case Operator.LessOrEqualThan:
                    return Expression.LessThanOrEqual(member, constant);
                default:
                    throw new Exception($"The type {queryFilter.Operator} not is a type selector valid.");
            }
        }

но с этим выражением я получил сообщение об ошибке, это код

private static Expression GetComplexExpression<T>(ParameterExpression parameter, QueryFilter queryFilter)
{
    MemberExpression member = Expression.PropertyOrField(parameter, queryFilter.PropertyName);

    MethodInfo method = typeof(HashSet<int>).GetMethods(BindingFlags.Public | BindingFlags.Instance)
        .Single(x => x.Name == "Contains" && x.IsFinal && x.GetParameters().Length == 1);
    var constant = Expression.Constant(queryFilter.Values);
    MethodCallExpression methodCallExpression = Expression.Call(method, constant, member);

    return methodCallExpression;
}

Я ищу в Google, но единственный результат моих поисков - это код в stackoverflow:

Построить лямбда-выражения с помощью Contains Большое спасибо за интерес ...

1 Ответ

0 голосов
/ 06 мая 2020

Продолжив попытки, я нашел ответ на свою проблему, приведенный выше код был близок.

private static Expression GetComplexExpression<T>(ParameterExpression parameter, QueryFilter queryFilter)
{
    MemberExpression value = Expression.PropertyOrField(parameter, queryFilter.PropertyName);

    MethodInfo method = typeof(HashSet<string>)
        .GetMethods(BindingFlags.Public | BindingFlags.Instance)
        .Single(x => x.Name == "Contains" && x.IsFinal && x.GetParameters().Length == 1);

    ConstantExpression listContains = Expression.Constant(queryFilter.Values);

    MethodCallExpression body = Expression.Call(listContains, method, value);

    return body;
}

Я меняю только используемый метод для этого

public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments);

Надеюсь помогу другим с моим ответом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...