Как написать метод List All, используя деревья выражений? - PullRequest
0 голосов
/ 11 мая 2018

У меня есть фрагмент кода ниже.

var list= new List<CustomClass>(){ new CustomClass(){Id=10}};
var result= list.All(a=>a.Id==10);

Как мы можем записать его в дерево выражений?

Цель: Это часть логики дерева больших выражений, которую мы реализуем, яЯ просто застрял при создании дерева выражения для метода «Все» в списке.

Спасибо

1 Ответ

0 голосов
/ 20 мая 2018

Не совсем понятно, что вы пытаетесь сделать, но давайте начнем отсюда ...

Это метод Enumerable.All:

static readonly MethodInfo allTSource = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                         where x.Name == nameof(Enumerable.All)
                                         let args = x.GetGenericArguments()
                                         where args.Length == 1
                                         let pars = x.GetParameters()
                                         where pars.Length == 2 &&
                                             pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                             pars[1].ParameterType == typeof(Func<,>).MakeGenericType(args[0], typeof(bool))
                                         select x).Single();

Тогда лямбда-выражение используется в .All(...):

// a => 
var par = Expression.Parameter(typeof(CustomClass), "a");

// a.Id
var id = Expression.Property(par, nameof(CustomClass.Id));

// 10
var val = Expression.Constant(10);

// a.Id == 10
var eq = Expression.Equal(id, val);

// a => a.Id == 10
var lambda = Expression.Lambda<Func<CustomClass, bool>>(eq, par);

Тогда проблема: неясно, является ли list константой или внешним выражением ... Я не знаю, как связать мой код с вашим ... Скажем для простоты, что это постоянная:

// Unclear what lst should be, a parameter of an external lambda or a constant
var lst = Expression.Constant(list);

// list.All(...)
var all = Expression.Call(allTSource.MakeGenericMethod(typeof(CustomClass)), lst, lambda);

// () => list.All(...)
Expression<Func<bool>> exp = Expression.Lambda<Func<bool>>(all);
Func<bool> fn = exp.Compile();
bool res = fn();
...