Простое предложение Where в дереве выражений - PullRequest
3 голосов
/ 12 сентября 2011

Я пытаюсь создать простое предложение Where.

Это код, который не работает:

РЕДАКТИРОВАТЬ теперь этот код работает нормально (благодаря ответам ниже).

public class Item
{
    public int Value { get; set; }
    public string Name { get; set; }
}

var _List = new List<Item>
{
    new Item{ Name = "Smith", Value = 1},
    new Item{ Name = "Smith", Value = 2},
    new Item{ Name = "Wesson", Value = 3},
    new Item{ Name = "Wesson", Value = 4},
};

// Where(x => x.Value == 1)
var _Type = typeof(Item);
var _Prop = _Type.GetProperty("Value");
var _Param = Expression.Parameter(_Type, _Prop.Name);
var _Left = Expression.PropertyOrField(_Param, _Prop.Name);
var _Right = Expression.Constant(1, _Prop.PropertyType); 
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param); 
var _Result = _List.AsQueryable().Where(_Where);

Спасибо.

1 Ответ

4 голосов
/ 12 сентября 2011

Есть несколько проблем с вашим кодом:

  1. Вам нужно передать 1, а не "1" для целочисленной константы 1.

    var _Right = Expression.Constant(1, _Prop.PropertyType);
    
  2. Expression.Equals, если два дерева выражений равны. Возвращает bool.

    Expression.Equal возвращает дерево выражений, которое представляет проверку на равенство.

    var _Body = Expression.Equal(_Left, _Right);
    
  3. Параметр имеет тип Item, а не int.

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
    
  4. Список реализует IEnumerable , но не IQueryable .

    IEnumerable работает с делегатами, а IQueryable работает с деревьями выражений.

    Так что вам нужно либо скомпилировать дерево выражений для делегата

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
    var _Result = _List.Where(_Where);
    

    или преобразовать список в IQueryable .

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
    var _Result = _List.AsQueryable().Where(_Where);
    

Рабочий код:

// Where(x => x.Value == 1)
var _Param = Expression.Parameter(typeof(Item), "x");
var _Left = Expression.PropertyOrField(_Param, "Value");
var _Right = Expression.Constant(1);
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
var _Result = _List.Where(_Where);
...