3

私はしばらくの間動的LINQをいじっていますが、その秘密をまだ学んでいません。

次のような解析したい式があります。

"document.LineItems.Select(i => i.Credit).Sum();"

これの解析中に、LineItemsコレクションでSelect関数を呼び出す必要があるポイントに到達します。Expression.Callのファクトリメソッドを使用しています。

Expression.Call(
    typeof(Queryable),
    "Select",
    new Type[] { typeof(LineItem), typeof(decimal?) },
    expr,
    Expression.Lambda(expression, new ParameterExpression[] { Expression.Parameter(typeof(LineItem) }));

現時点では

expr:          document.LineItems    [ICollection<LineItem>]  
expression:    LineItem.Credit       [decimal?]

まだ具体化されていない。現在、エクスプレッションツリーを構築しています。

さて、問題:

このExpresssion.Callは、例外をスローします。「タイプ'System.Linq.Queryable'のジェネリックメソッド'Select'は、指定されたタイプの引数および引数と互換性がありません」;

Expression.Callの最初の引数を変更して、「Queryable」ではなく「System.Linq.Enumerable」で「Select」を探すことで、簡単に解決できます。

しかし、それは私が望んでいることではありません。Sum()を計算するためだけにすべてのLineItemを取り込む必要はありません。これは、明らかにEnumerableの場合です。Queryableを機能させたい。

また、解析の最後の部分であるSum()についても、Queryable Sum()が同じ例外をスローするため、Enumerable Sum()を使用する必要があります。

MSDNを確認しましたが、「Select」関数の両方の署名が同一であるため、一方が機能し、もう一方が機能しない理由がわかりません。

ヘルプやポインタはすべて承認されます。

よろしく、

4

1 に答える 1

4

問題はそれLineItemsがであるICollection<LineItem>のに対し、最初のパラメータは。をQueryable.Select必要とすることIQueryable<LineItem>です。ICollection<T>を実装するだけIEnumerable<T>で、それがで機能する理由ですEnumerable.Select

のタイプをに変更する必要がありexprますIQueryable<LineItem>

Queryable.AsQueryableメソッドを使用してこれを実行できるはずです。Document次の関数は、特定のインスタンスのクレジットプロパティ値を合計する式を作成します。

public static Expression<Func<decimal?>> CreateSumLineItemsExpr(Document document)
{
    var docExpr = Expression.Constant(document);
    var itemsExpr = Expression.Property(docExpr, "LineItems");

    Expression<Func<LineItem, decimal?>> selector = i => i.Credit;
    var queryableExpr = Expression.Call(typeof(Queryable), "AsQueryable", new[] { typeof(LineItem) }, itemsExpr);
    var selectExpr = Expression.Call(typeof(Queryable), "Select", new[] { typeof(LineItem), typeof(decimal?) }, queryableExpr, selector);
    var sumExpr = Expression.Call(typeof(Queryable), "Sum", null, selectExpr);

    return Expression.Lambda<Func<decimal?>>(sumExpr);
}
于 2012-12-08T13:31:25.637 に答える