1

次のコードは、一連の「ゲッター」(データ取得クライアント)で同じセレクターを一般的に呼び出して、すべての結果を組み合わせることができるようにすることで、冗長なコードを減らすことを目的としています。最終的な結果セットは待機可能であり、すべてのセレクターが完了するのを待っている間、システムがブロックしないようにします。

public async Task<T> GetBulkAsync<T>(Func<IGetter, Task<T>> selector) where T : IEnumerable<T>
{
    Task<T>[] tasks = new Task<T>[this.getters.Count];
    for (int i = 0; i < this.getters.Count; i++)
    {
        tasks[i] = selector(this.getters[i]);
    }

    T[] results = await Task.WhenAll(tasks);

    return results.SelectMany<T, T>(r => r);
}

しかし、ここで私のデザインに問題が発生します。単にシングルを取得するセレクターを使用したい場合がありますが、セレクターがまったく異なるものIDataを取得するIEnumerable<IData>場合があります。List<IData>

リフレクションを使用してジェネリックコレクションの特殊なケースを処理することを考えましたが、それは面倒であり、処理するコレクションのタイプごとに追加の作業が必要です。

私が気にかけているIEnumerable<IData>(または実際にIEnumerable<T>)主な理由は、大きな結果セットのすべての結果をフラット化するために、LinqのSelectManyを使用したいからです。各セレクターが。で戻ってくる場合は、ではなくIEnumerable<T>1つに減らす必要があります。IEnumerable<T>IEnumerable<IEnumerable<T>>

コレクションタイプに制約があり、リフレクションを使用せずに、いくつかの異なるジェネリックメソッドを作成する以外に、この問題を解決するための良いアプローチはありますか?

4

1 に答える 1

0

1 つの型パラメーターに依存する代わりに、2 つを使用して、次のように変換/射影関数を最後に提供します。

public async Task<TResult> GetBulkAsync<T, TResult>(
    Func<IGetter, Task<T>> selector,
    Func<IEnumerable<T>, TResult> aggregateSelector) 
        where T : IEnumerable<T>
{
    Task<T>[] tasks = new Task<T>[this.getters.Count];
    for (int i = 0; i < this.getters.Count; i++)
    {
        tasks[i] = selector(this.getters[i]);
    }

    T[] results = await Task.WhenAll(tasks);

    return results.Select<T, TResult>(aggregateSelector);
}

aggregateSelector基本的にそれぞれIEnumerable<T>を新しいTResultインスタンスに変換し、 を返しますIEnumerable<TResult>

ただし、実際にはそうする必要がないのに、関数で発生する構成に依存しているため、これはお勧めしません。

代わりに、次のように一連のシーケンスを返す必要があると思います。

public async Task<IEnumerable<IEnumerable<T>>> GetBulkAsync<T>(
    Func<IGetter, Task<T>> selector) 
        where T : IEnumerable<T>
{
    Task<T>[] tasks = new Task<T>[this.getters.Count];
    for (int i = 0; i < this.getters.Count; i++)
    {
        tasks[i] = selector(this.getters[i]);
    }

    T[] results = await Task.WhenAll(tasks);

    return results.Select(t => t.Result):
}

このようにして、このメソッドを変更しなくても、結果を好きなように構成できます。

于 2012-10-04T18:41:11.103 に答える