2016-05-25 4 views
1

everyone。私は過去数時間のうちにGoogleとの回答とイミディエイトウィンドウを使った必死のテストを試してみましたが、私は正しい質問をしていないと思います。"複合型"のLambdaExpressionを使用してリストをソート

私のアプリケーションにはOrderByExtenderがあります。これは、プロパティ名とブール値を使用して並べ替えを行うだけで、ASCまたはDESCソートかどうかを判断できます。

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, string key, bool isAscending) 
    { 
     LambdaExpression sortLambda = BuildLambda<T>(key); 

     if (isAscending) 
      return collection.OrderBy((Func<T, object>)sortLambda.Compile()); 
     else 
      return collection.OrderByDescending((Func<T, object>)sortLambda.Compile()); 
    } 

    private static LambdaExpression BuildLambda<T>(string key) 
    { 
     ParameterExpression TParameterExpression = Expression.Parameter(typeof(T), "p"); 
     LambdaExpression sortLambda = Expression.Lambda(Expression.Convert(Expression.Property(TParameterExpression, key), typeof(object)), TParameterExpression); 
     return sortLambda; 
    } 

共通型プロパティ(文字列、intなど)を使用すると、魅力的です。しかし、今私は次のシナリオを考え出しました:BusinessOrderというオブジェクトがあり、その内部にタイプクォーターのプロパティがあります。このQuarterオブジェクトには、Year(int)、Quarter(int)、およびAbbreviation(string)の3つのプロパティがあります。 Abbreviationプロパティを使用してOrderByを実行する必要があります。言い換えれば、私がしなければならない:

BusinessOrderList.OrderBy(b => b.Quarter.Abbreviation); 

しかし、私は「Quarter.Abbreviation」とExtenderの方法のようなキーパラメータ何かとして渡すことで、私のエクステンダー内のソート可能性のこの種を入れたいことがありますことを理解していますプロパティを「複雑なオブジェクト」の中に入れるという問題。

sortLambda変数を作成する "Expression.Lambda"メソッドの中に何かできることはあると思いますが、式を使用してこの動作を複製する方法を理解できませんでした。誰か助けてくれますか?前もって感謝します。

答えて

2

複雑なプロパティに一度にアクセスすることはできません。あなたは再帰的に表現チェーンを構築する必要があります。

private Func<TInput, object> BuildLambda<TInput>(string complexPropertyPath) 
    { 
     var parameter = Expression.Parameter(typeof(TInput), "p"); 

     var propertyPathParts = complexPropertyPath.Split('.'); 
     MemberExpression complexPropertyAccessExpression = null; 
     foreach (var propertyPathPart in propertyPathParts) 
     { 
      complexPropertyAccessExpression = complexPropertyAccessExpression == null 
       ? Expression.Property(parameter, propertyPathPart) 
       : Expression.Property(complexPropertyAccessExpression, propertyPathPart); 
     } 

     var lambda = (Func<TInput, object>)Expression.Lambda(complexPropertyAccessExpression, parameter).Compile(); 

     return lambda; 
    } 
+0

BEAUTIFULようにそれを呼び出す必要があります!より良いことができませんでした!それは、私がやりたいことのようなものです、ただ必要な知識を持っていません!ありがとうございました! – thiagoprzy

0

を可能にした場合、私はExpression<Func<T, object>> keyパラメータでstring keyパラメータを交換することをお勧めします。そのようにして、あなたの関数呼び出しは、あなたが説明したのと同じようにBusinessOrderList.OrderBy(b => b.Quarter.Abbreviation);になることができます。とにかく、すべてのOrderBy/OrderByDescendingメソッドはこの式を文字列の代替として受け入れるので、文字列としてkeyを保持することでどのような利点が得られるか分かりません。

0

あなたはあなたのコレクション

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, 
          Func<IEnumerable<T>,IOrderedEnumerable<T>> OrderBy) 
{ 
    if(OrderBy != null) 
     return OrderBy(collection); 
    return collection; 
} 

をソートするためFuncを渡すことができますが、この

{ 
    Func<IEnumerable<Book>,IOrderedEnumerable<Book>> sort = 
    list => list.OrderBy(B=>B.Author.Name).ThenByDescending(B=>B.Title) ; 

    List.OrderBy(sort); 

} 
関連する問題