C # Reflection Expression Linq - PullRequest
       0

C # Reflection Expression Linq

0 голосов
/ 23 ноября 2018

У меня возникли некоторые проблемы с динамически генерируемыми лямбда-выражениями C #.

Учитывая следующий сценарий:

public class Person {
    public long Id { get; set; }
    public string Name { get; set; }
}

List<Person> persons = new List<Person> () {
    new Person { Id = 1, Name = "Foo" },
    new Person { Id = 2, Name = "Bar" },
    new Person { Id = 3, Name = "Baz" },
    new Person { Id = 4, Name = null },
};

Теперь выполняем следующий код

ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;

MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);

Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new[] { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));

clausule = Expression.And(notNull, clausule);

var exp = Expression.Lambda<Func<T, bool>>(clausule, param);

Приведенный выше код генерирует следующее выражение.

//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))

Теперь, пытаясь применить это к моему списку.

Фильтр ниже работает

var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();

Тот, что нижегенерирует исключение для объекта Null (из-за имени Id 4)

var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();

То же выражение, генерируемое лямбда-выражением, генерирует exp при вводе вручную, работает.Кто-нибудь знает способ решить это?

Br,

1 Ответ

0 голосов
/ 23 ноября 2018

And - &;вы хотите использовать AndAlso (&&):

clausule = Expression.AndAlso(notNull, clausule);

Если вы сомневаетесь, sharplab.io - отличный инструмент здесь;если я использую:

Expression<Func<Person, bool>> filter
        = arg => arg.Name != null && arg.Name.ToLower().Contains("bar");

, это говорит мне, что оно компилируется, чтобы быть эквивалентным:

// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...

(обратите внимание, что оно должно лежать в отношении некоторых инструкций, так как оно компилируетсяк вещам, которые на самом деле не могут быть выражены в необработанном C #)

увидеть это в действии

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