Неспецифический тип в Expression.Lambda Generics - PullRequest
4 голосов
/ 12 сентября 2011

Следующий код работает нормально (он создает общий OrderBy):

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

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

var _Type = typeof(Item);

// OrderBy
var _OrderByProperty = _Type.GetProperty("Value");
var _OrderByParameter = Expression.Parameter(typeof(Item), "x");
// OrderBy(x => x.Value)
var _OrderByBody = Expression.Property(_OrderByParameter, _OrderByProperty.Name);
var _OrderByLambda = Expression.Lambda<Func<Item, Int32>>
    (_OrderByBody, _OrderByParameter);
// apply the OrderBy
_List = _List.OrderBy(_OrderByLambda);

Но я бы хотел изменить эту строку следующим образом:

var _OrderByLambda = Expression.Lambda<Func<Item, object>>
    (_OrderByBody, _OrderByParameter);

Такое изменение сделало бы тип данных упорядоченного столбца общим. Однако такое изменение приводит к следующему исключению:

Выражение типа «System.Int32» нельзя использовать для типа возвращаемого значения «System.Object»

Есть идеи?

РЕДАКТИРОВАТЬ , спасибо за ваши ответы, это прекрасно работает:

var _OrderByProperty = _Type.GetProperty("Value");
var _OrderByParameter = Expression.Parameter(typeof(Item), "x");
// OrderBy(x => x.Value)
var _OrderByBody = Expression.Property(_OrderByParameter, _OrderByProperty.Name);
var _OrderByConverted = Expression.Convert(_OrderByBody, typeof(object));
var _OrderByLambda = Expression.Lambda<Func<Item, object>>
    (_OrderByConverted, _OrderByParameter);
// apply the OrderBy
_List = _List.OrderBy(_OrderByLambda);

Ответы [ 3 ]

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

Вы должны указать, что тип возвращаемого тела равен System.Object. Вы можете сделать это, вставив преобразование (что C # делает неявно):

_OrderByBody = Expression.Convert(_OrderByBody, typeof(object));
1 голос
/ 12 сентября 2011

Проблема в том, что Expression.Property(_OrderByParameter, _OrderByProperty.Name); создает выражение, которое возвращает int. Вам нужно будет его упаковать. Так что вам нужно обернуть его в выражение Box. Однако, если вы хотите сделать его универсальным, вы не должны упаковывать объекты

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

Проблема в этой строке:

_List = _List.OrderBy(_OrderByLambda);

Этот метод ожидает параметр Function<Item, int> (поскольку _Type.GetProperty("Value") возвращает Int32), поэтому вы не можете использовать тип Expression.Lambda<Func<Item, object>>.

Если вам нужна универсальная функция object, вам нужно изменить определение класса следующим образом:

public class Item
{
    public object Value { get; set; }
    public string Name { get; set; }
}
...