2010-05-05 63 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