如何从实际类型推断出TResult?

时间:2010-05-05 15:16:38

标签: c# generics linq-to-entities type-inference

我使用的是Entity Framework,ASP.NET和C#3.5 我借用以下代码来使用GridView中的sortExpression而不是实体的属性进行排序:

    public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
    {
        string[] sortParts = sortExpression.Split(' ');
        var param = Expression.Parameter(typeof(T), string.Empty);

        var property = Expression.Property(param, sortParts[0]);

        var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);           

        if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
        {
            return source.AsQueryable<T>().OrderByDescending(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy(sortLambda);
    }

问题是LINQ to Entities不支持转换为对象。而不是Func,我需要实际的返回类型而不是对象。我找到了如何做到这一点:

    public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
    {
        string[] sortParts = sortExpression.Split(' ');
        var param = Expression.Parameter(typeof(T), string.Empty);

        var property = Expression.Property(param, sortParts[0]);

        // NEW CODE HERE
        Type propertyType = property.Type;
        Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(T), propertyType);
        var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, propertyType), param);
        //var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);

        if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
        {
            return source.AsQueryable<T>().OrderByDescending(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy(sortLambda);
    }

现在的问题是,如果我有一个Int32,它将不会转换为对象,它仍然是返回类型。我这样解决了这个问题:

    public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
    {
        string[] sortParts = sortExpression.Split(' ');
        var param = Expression.Parameter(typeof(T), string.Empty);

        var property = Expression.Property(param, sortParts[0]);

        // New code here
        Type propertyType = property.Type;
        Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(T), propertyType);

        // NEWEST CODE HERE
        var sortLambda = Expression.Lambda(lambdaType, Expression.Convert(property, propertyType), param);
        //var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, propertyType), param);
        //var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);


        if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
        {
            return source.AsQueryable<T>().OrderByDescending(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy(sortLambda);
    }

然而,这不再编译。错误是:

  

无法从用法推断出方法'System.Linq.Enumerable.OrderByDescending(System.Collections.Generic.IEnumerable,System.Func)'的类型参数。尝试显式指定类型参数。

问题在于我不想明确指定类型参数。

有没有人知道如何解决这个问题或者无论如何从“propertyType”推断出TResult类型?

1 个答案:

答案 0 :(得分:1)

使用hererefinement here方法应该可以满足您的需求。必要时,它使用反射来做中间的内脏,但它的工作原理。另请注意,Expression.GetFuncTypeExpression.GetActionType可以避免您的方法中的一些工作。