ラムダ式にGroupByを動的に追加する

expression-trees linq

質問

さて、私はラムダ式とLINQ式ツリーを完全に "取得"していないことを認めます。私がやっていることの多くは、切断して貼り付けて、何が効果があるか見ることです。私は多くのドキュメンテーションを見てきましたが、まだ私の "aha"の瞬間はまだ見つかりませんでした。

それは言っていると...

私は動的にGroupBy式をLinq式に追加しようとしています。私はここで質問に従った: Enumerable.GroupByへのLinq.Expressionの作成を助ける必要がある

私がそこに見たものを実装しようとしました。

まず、私のデータベースのためのエンティティクラスと、ObjCurLocViewNormalizedというテーブルがあります

私は最初の呼び出しを行うメソッドを持っている、

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

私は電話することができます:

IQueryable<MetAmericanLinqDataModel.ObjCurLocViewNormalized> locations = american.getLocations();

これまでのところ問題ありません。

今、私は任意の列で、このような呼び出しでグループ化したい:

var grouped = locations.addGroupBy(childLocationFieldName);

今、私は方法があります:

static public System.Linq.IQueryable<System.Linq.IGrouping<string, TResult>> addGroupBy<TResult>(this IQueryable<TResult> query, string columnName)
{

    var providerType = query.Provider.GetType();
    // Find the specific type parameter (the T in IQueryable<T>)
    var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
    var tableType = iqueryableT.GetGenericArguments()[0];
    var tableName = tableType.Name;

    var data = Expression.Parameter(iqueryableT, "query");
    var arg = Expression.Parameter(tableType, tableName);
    var nameProperty = Expression.PropertyOrField(arg, columnName);
    var lambda = Expression.Lambda<Func<TResult, string>>(nameProperty, arg);

    var expression = Expression.Call(typeof(Enumerable), 
                                    "GroupBy", 
                                    new Type[] { tableType, typeof(string) },
                                    data, 
                                    lambda);
    var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg); // this is the line that produces the error I describe below
    var result = query.GroupBy(predicate).AsQueryable();
    return result;
}

これはすべてコンパイルされますが、実行するとエラーが発生します:

System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Linq.IGrouping`2[System.String,MetAmericanLinqDataModel.ObjCurLocViewNormalized]]' cannot be used for return type 'System.String'

エラーは次の行から出力されます。

 var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg);

私は、動的にWhere句を式に追加して成功した作品からこのコードをコピーして適応させています。だから私はここで暗闇の中で刺すようなものだ。

もし誰かがこれについていくつかの光を当てるのを助けることができるなら、明らかに完全な作業コードを掲示し、私のために私の考えをすべて実行することは素晴らしいでしょう:)しかし、あなたがちょうどこれが間違っている理由、または私の頭を包む方法これらのコンセプトの周りに、それは素晴らしいだろう。ラムダ式の基礎と動的式ツリーの構築との間のギャップを埋めるのに本当に役立つドキュメントを指すことができれば、それは素晴らしいことです。明らかに私の知るところに大きな穴がありますが、私はこの情報が他の人に役立つと思います。

あなたの時間のおかげで誰もが、もちろん私は答えを見つける場合は、私はここにそれを投稿します。

再度、感謝します。

ドン

人気のある回答

ソリューションはかなりシンプルでなければなりません:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>(
    IQueryable<T> source, string column)
{
    PropertyInfo columnProperty = typeof(T).GetProperty(column);
    var sourceParm = Expression.Parameter(typeof(T), "x");
    var propertyReference = Expression.Property(sourceParm, columnProperty);
    var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm);

    return source.GroupBy(groupBySelector);
}

次のようなサンプルクラスを想定します。

public class TestClass
{
    public string TestProperty { get; set; }
}

あなたはこれを次のように呼び出します:

var list = new List<TestClass>();
var queryable = list.AsQueryable();
DynamicGroupBy<TestClass, string>(queryable, "TestProperty");



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ