2010-05-05 47 views
2

我使用实体框架,ASP.NET和C#3.5 我借下面的代码,使使用的SortExpression从GridView控件,而不是实体的属性排序可能:如何从实际类型推断TResult?

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

使用的方法here,与refinement here,应该做你需要的。必要时它使用反射来做中间的胆量,但它的工作原理。还请注意,Expression.GetFuncTypeExpression.GetActionType可以避免您的方法中的一些工作。

+0

谢谢,正是我在找的! – Calin 2010-05-17 12:00:57