Динамические данные — реализация IQueryable для List‹int› Contains()

У меня есть ряд объектов, все из которых имеют аналогичное свойство, которое представляет собой список идентификаторов групп, к которым они принадлежат (многие родители на одного ребенка).

У меня возникли проблемы с программной реализацией выражения Linq, необходимого для правильной работы этого фильтра.

Это то, что у меня есть до сих пор:

IQueryable result = null;

   if (!string.IsNullOrWhiteSpace(this.ddlRouteNames.SelectedValue))
   {
      ConstantExpression ce = Expression.Constant(int.Parse(this.ddlRouteNames.SelectedValue));
      ParameterExpression pe = Expression.Parameter(source.ElementType);
      MemberExpression me = Expression.Property(pe, this.Column.Name);
      MethodCallExpression mce = Expression.Call(typeof(List<int>), "Contains", new[] { typeof(int) }, me, ce);

      result = source.Provider.CreateQuery(mce);
   }

return result;

Я получаю исключение при попытке создать выражение MethodCallExpression:

Метод «Содержит» не существует для типа «System.Collections.Generic.List`1[System.Int32]».

Любые указатели на то, с чего начать?


person Sonny Boy    schedule 07.05.2013    source источник
comment
Я в замешательстве, вы сказали это почти правильно в вашем предыдущем вопросе.   -  person svick    schedule 07.05.2013
comment
В этом вопросе метод был статическим.   -  person Vyacheslav Volkov    schedule 07.05.2013
comment
Другой вопрос приводит к исключению, когда я пытаюсь создать запрос: выражение аргумента не реализует System.Linq.IQueryable`1[System.Boolean].   -  person Sonny Boy    schedule 07.05.2013


Ответы (2)


Ваш вызов метода неверен. Чтобы вызвать нестатический метод, вам необходимо предоставить экземпляр, содержащий этот метод. Вот пример вызова метода Contains:

var list = new List<int> {1};
//Target for invoke method
var target = Expression.Constant(list);
var methodCallExpression = Expression.Call(target, typeof(List<int>).GetMethod("Contains"), Expression.Constant(1));

Если в вашем коде me это элемент, содержащий List, код будет выглядеть так:

Expression.Call(me, typeof(List<int>).GetMethod("Contains"), ce);
person Vyacheslav Volkov    schedule 07.05.2013
comment
Приближаемся... Теперь часть MethodCallExpression работает правильно, но когда я пытаюсь использовать источник IQueryable для создания запроса, я получаю следующее исключение: Выражение аргумента не реализует System.Linq.IQueryable`1[System.Boolean ]. - person Sonny Boy; 07.05.2013
comment
Какой тип переменной source? - person Vyacheslav Volkov; 07.05.2013
comment
source — это IQueryable, который передается в метод GetQueryable, который переопределяется из наследования от QueryableFilterUserControl. - person Sonny Boy; 07.05.2013

Type в сигнатуре метода, которую вы использовали:

public static MethodCallExpression Call(Type type, 
                                        string methodName, 
                                        Type[] typeArguments, 
                                        params Expression[] arguments);

указывает тип, содержащий конкретный метод static.

Вам нужен экземпляр типа для этого метода - пример (связанный с вашим комментарием):

var par = Expression.Parameter(typeof(int), "par");            
var inst = Expression.Parameter(typeof(List<int>), "inst");
var body = Expression.Call(inst, typeof(List<int>).GetMethod("Contains"), par);
var exp = Expression.Lambda(body, inst, par);
var deleg = exp.Compile();

var lst = new List<int>() { 1, 2, 3, 4, 5 };
var exists = deleg.DynamicInvoke(lst, 3);
person jwaliszko    schedule 07.05.2013
comment
Спасибо. Есть ли что-то подобное, что я могу использовать для достижения желаемых результатов? По сути, я пытаюсь написать выражение, которое будет видеть, появляется ли выбранный идентификатор в списке идентификаторов этого объекта. - person Sonny Boy; 07.05.2013