2016-05-27 10 views
0

ソートのために動的に式ツリーを構築しようとしています。並べ替えは、私のWeb APIのアクションフィルターで行われます。したがって、実行時までオブジェクトのタイプは不明です。
アクションフィルタのレベルでは:動的オブジェクトのlinq式ツリーの作成

ここで概要を説明します

IEnumerable<object> model = null; 
context.Response.TryGetContentValue(out model); 
model=model.OrderByExtension(orderByField, orderDirection); 
context.Response.Content=new ObjectContent<IEnumerable<object>>(model, new JsonMediaTypeFormatter()); 

と拡張方法:Expression.Callオン

public static IQueryable<T> OrderByExtension<T>(this IQueryable<T> source, string sortProperty, Sorting.SortingOption sortOrder) 
     { 
      var type = source.FirstOrDefault().GetType(); //Gets the type of object passed, since typeof(T) is only object at this point 
      var property = type.GetProperty(sortProperty); 
      var parameter = Expression.Parameter(type, "p"); 
      var propertyAccess = Expression.MakeMemberAccess(parameter, property); 
      var orderByExp = Expression.Lambda(propertyAccess, parameter); 
      var typeArguments = new Type[] { typeof(T), property.PropertyType }; 
      var methodName = sortOrder == Sorting.SortingOption.Asc ? "OrderBy" : "OrderByDescending"; 
      var resultExp = Expression.Call(typeof(Queryable), methodName, typeArguments, source.Expression, Expression.Quote(orderByExp)); 

      return source.Provider.CreateQuery<T>(resultExp); 
     } 

- 私はエラーを取得します: 'System.Linq.Queryable'型の汎用メソッド 'OrderByDescending'は、指定された型引数および引数と互換性がありませんts。

OrderByメソッドが呼び出されたときに、「オブジェクト」タイプと実際のタイプとの間に不一致があると仮定しています。

これを動作させる方法はありますか?

ありがとうございます。 ps:.MakeGenericMethod経由でOrderByの汎用メソッドを作成しようとしましたが、成功しませんでした。

+0

この回答[Entity FrameworkでOrder By Expressionを動的に構築する方法](http://stackoverflow.com/a/34908081/296861)を参照してください。 – Win

+0

私はそれを見ました。しかし、これらすべてのシナリオでは、タイプTはDTOのタイプと正しく認識されます。残念ながら、私の場合、typeof(T)はオブジェクトになります。 – Newbee

答えて

0

問題は、ソース式(object)のタイプではなく、実際の基礎となるタイプの関数の式を生成していることです。生成された式で型にコンバージョンを追加する必要があります。

public static IQueryable<object> OrderByExtension(this IQueryable<object> source, string sortProperty, SortOrder sortOrder = SortOrder.Unspecified) 
{ 
    var sourceType = typeof(object); 
    var underlyingType = source.First().GetType(); 
    var propertyType = underlyingType.GetProperty(sortProperty).PropertyType; 
    var param = Expression.Parameter(sourceType); 
    var body = Expression.Property(
     Expression.Convert(param, underlyingType), sortProperty 
    ); 
    var lambda = Expression.Lambda(body, param); 

    var sortMethod = sortOrder == SortOrder.Descending ? "OrderByDescending" : "OrderBy"; 
    var expr = Expression.Call(typeof(Queryable), sortMethod, new Type[] { sourceType, propertyType }, 
     source.Expression, lambda 
    ); 
    return source.Provider.CreateQuery<object>(expr); 
} 
+0

パーフェクト - 魅力的な作品!オブジェクトから基底型への変換が欠けていました。どうもありがとうございます ! – Newbee

関連する問題