1

PredicateBuilder を使用して、特定のレコードのセットがすべて Expression 内に存在するかどうかを判断する方法を理解しようとしています。したがって、仕様として OrderId と ProductId のリストが与えられた場合、Order の OrderDetail レコードにすべての仕様項目が含まれているかどうかを知りたいと思います。それらの1つまたは一部だけではなく、それらすべてです。

だから私はできる:

var inner = PredicateBuilder.False<OrderDetail>();

foreach (int spec in specs)
{
   temp = spec;            
   inner = inner.Or(d => d.ProductId == temp);
}

var outer = PredicateBuilder.True<OrderDetail>();

outer = outer.And(d => d.OrderId == orderId);
outer = outer.And(inner);

しかし、結果を取得した後、a) 重複を排除し (私の場合、複数の OrderDetails が同じ ProductId を持つ可能性があるため)、b) 結果のカウントを仕様のカウントと比較する必要があります。これはすべて Expression の外で実行できますが、結果がブール値になるように Expression 内のすべてを評価するエレガントな方法はありますか?

つまり、式を自己完結型にして、そのまま渡すことができるようにしたいと思います。また、それを渡す人は、それが真かどうかを判断するために「後処理」を行う方法を知る必要がありません。 .

4

1 に答える 1

0

あなたが示した例については、別の見方をすることで、はるかに簡単にできると思います。

OrderDetails から作業する代わりに、スペックから始めて、それらが OrderDetails コレクション内の All であることを確認してください。この 1 行のコードは、特定の orderID にすべての仕様が含まれていることを確認するという要件を満たし、まったく複雑ではありません。

bool containsAllSpecs = specs.All 
    (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s));

OrderDetail クラス内から Expression を構築しようとするのが不可能な理由は、式がコレクション全体の 1 つの項目にのみ適用され、そのためコレクション内の他の項目がわからないためだと思います。

できるだけ多くのロジックを非表示にする拡張機能を本当に作成したい場合は、これを拡張機能に入れることができます。

static class MyExtensions
{
    public static bool ContainsAllSpecs(this IEnumerable<OrderDetail> orderDetails,
        int orderId,
        IEnumerable<int> specs)
    {
        return specs
         .All (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s));
    }
}

そして、次のようなコードから呼び出します。

bool containsAllSpecs = orderDetails.ContainsAllSpecs(orderId, specs);
于 2012-06-17T18:22:36.520 に答える