Expression.Lambda Generics中的非特定类型

时间:2011-09-12 19:36:43

标签: c# linq sql-order-by expression-trees

以下代码工作正常(它构建一个通用的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 个答案:

答案 0 :(得分:6)

您需要指定正文的返回类型正好为System.Object。您可以通过插入转换(C#隐式执行的操作)来执行此操作:

_OrderByBody = Expression.Convert(_OrderByBody, typeof(object));

答案 1 :(得分:1)

问题是Expression.Property(_OrderByParameter, _OrderByProperty.Name);创建了一个返回int的表达式。你需要把它装箱。所以你需要将它包装在Box表达式中。但是,如果你想使它成为通用的,你就不应该装箱子

答案 2 :(得分:0)

问题出在这一行:

_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; }
}