1

結果のシェーピング/投影を含む、メモリ内コレクション ( IEnumerable<T>、 not )の仕様パターンを実装する堅牢でエレガントな、および/または標準的な方法はありますか?IQueryable<T>

for criteriaを使用すると、明らかに句/メソッドFunc<T, bool>のみがカバーされ、 .WhereSelect

これまでに思いついたアイデアは、Select操作を具体的にカバーする (しゃれた意図はありません) 別のデリゲートを仕様に含めることができるということです。実装は次のようになります。下部にあるように、リポジトリは単純に と の両方Whereを実行Selectし、仕様のデリゲート メンバーを渡します。

この解決策は問題なく機能するように見えますが、私が解決しようとしていた問題に対する既存のより良い解決策があることを何度も知ったので、質問するのは理にかなっているように思えました。

(仕様パターンを使用することを計画している理由は、おそらく、複雑なオブジェクトのメモリ内コレクションからさまざまな形で多くの結果を表示する必要があり、クエリを.単一の、見つけやすく、管理しやすい場所です。ただし、まったく別の場所を自由に提案してください。)

internal interface IMySpecification<TEntity, TResult>
{
    Func<TEntity, bool> Where { get; }
    Func<TEntity, TResult> Select { get; }
    bool IsSatisfiedBy(TEntity t);
    // ...  
}

internal interface IMyRepository<TEntity>
{
    // ...
    TResult GetSingle<TResult>(IMySpecification<TEntity, TResult> spec);
    IEnumerable<TResult> List<TResult>(IMySpecification<TEntity, TResult> spec);
}

internal class MyGenericRepository<T> : IMyRepository<T>
{
    protected IEnumerable<T> _collection;

    public MyGenericRepository(IEnumerable<T> list)
        => _collection = list;

    // ...

    public TResult GetSingle<TResult>(IMySpecification<T, TResult> spec)
        => List(spec).Single();

    public IEnumerable<TResult> List<TResult>(IMySpecification<T, TResult> spec)
        => (IEnumerable<TResult>)_collection.Where(spec.Where).Select(spec.Select);
}
4

1 に答える 1