表达式树中没有发生隐式转换

Moo*_*thy 6 .net c# linq expression-trees type-parameter

我遇到了一个场景,我需要根据输入对不同属性的自定义类型列表进行排序.在几篇文章的帮助下,我能够使用LINQ.Auring进行单元测试的通用实现,其中一个测试失败,因为当使用Expression树创建lamda表达式时发生了隐式转换.

下面我已经放了示例代码来理解问题(不确定为什么格式化不正确,对不起)

static class ExtensionMethods
{
 public static IEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> unSortedList, Func<TSource, object> selector, bool isAscending)
    {
       return isAscending ? unSortedList.OrderBy(selector) :                 unSortedList.OrderByDescending(selector);
}   
}

class Program
{

    class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    static void Main(string[] args)
    {
        var unOrderedStudents = new List<Student>
                           {
                               new Student{ Name="A", Age=20},
                               new Student{Name = "B", Age=19}
                           };


        //This Works
        var sortUsingLamda = unOrderedStudents.Sort<Student>(stud => stud.Age, true);


        //Exception - Expression of type 'System.Int32' cannot be used for return type 'System.Object'
        var sortUsingExpressionTree = unOrderedStudents.Sort<Student>( GetSortFunc<Student>("Age"), true);

        Console.WriteLine("Press any key to continue");
        Console.ReadLine();
    }



    private static Func<T, object> GetSortFunc<T>(string sortColumn)
    {
        var param = Expression.Parameter(typeof(T), "entity");

        var propertyExpression = Expression.Property(param, sortColumn);

        var boxingExpression = Expression.Convert(propertyExpression, typeof(object));

        return Expression.Lambda<Func<T, object>>(propertyExpression, param).Compile();

        //after adding Convert expression issue got fixed
        //return Expression.Lambda<Func<T, object>>(boxingExpression, param).Compile();

    }
} 
Run Code Online (Sandbox Code Playgroud)

在Main方法中,当我尝试将Func委托直接传递给Sort扩展方法时,它可以工作,但它失败了Expression树.

我发现了一个类似的问题,但是它讨论了约束类型参数.问题是否相同?有人可以帮助我理解这个问题.

Mar*_*ell 6

您需要使用盒装版本(您当前正在创建 boxingExpression,但最终的查询基于propertyExpression):

return Expression.Lambda<Func<T, object>>(boxingExpression, param).Compile();
Run Code Online (Sandbox Code Playgroud)

为什么这不是隐含的 - 这里根本没有隐式投射; Expression!= C#.Boxing是一项非常重要的操作,ExpressionAPI需要树中的特定节点.