2016-08-02 8 views
0

私はすべてのGenerateAsyncは異なる型のオブジェクトを生成し、この非同期メソッド呼び出しを使用してif条件のセットをDictionaryに変換するにはどうすればよいですか?

if (SectionContainedWithin(args, RegisterSection.StudentPersonalData)) 
    schoolRegister.StudentPersonalData = await _sectionGeneratorsProvider.StudentPersonalDataGenerator.GenerateAsync(args); 

if (SectionContainedWithin(args, RegisterSection.StudentAttendances)) 
    schoolRegister.StudentAttendances = await _sectionGeneratorsProvider.StudentMonthAttendancesGenerator.GenerateAsync(args); 

if (SectionContainedWithin(args, RegisterSection.Grades)) 
    schoolRegister.Grades = await _sectionGeneratorsProvider.GradesGenerator.GenerateAsync(args); 

// More generating here ... 

のように見えるいくつかのメソッド呼び出しを持っています。

public interface IGenerator<TResult, in TArgs> 
{ 
    Task<TResult> GenerateAsync(TArgs args); 
} 

にはどうすればいいので、私はアクションと条件のリストを定義することができますし、それらを反復処理、それらのif Sを書き換えることができます。 のような何か:

var sections = new Dictionary<bool, Func<Task>>() 
{ 
    { 
     SectionContainedWithin(args, RegisterSection.StudentPersonalData), 
     () => schoolRegister.StudentPersonalData = await _sectionGeneratorsProvider.StudentPersonalDataGenerator.GenerateAsync(args); 
    }, 

    // More generating here ... 
} 

foreach(var item in sections) 
{ 
    if(item.Key) 
    { 
     await item.Value(); 
    } 
} 

SOLUTION:

おかげで、私はDictionary<bool, Func<Task>>を作成するためのアイデアを落とし、それがより理にかなっているのでIReadOnlyDictionary<RegisterSection, Func<RegisterXml, RegisterGenerationArgs, Task>>でそれを置き換える@ピーター・dunihoの答えに。 複数のキーで、2つの真偽のみではありません。

は、だから私は私が正しくコード例を理解していれば、辞書は本当にこの仕事のための適切なツールではありません

private IReadOnlyDictionary<RegisterSection, Func<RegisterXml, RegisterGenerationArgs, Task>> CreateSectionActionsDictionary() 
{ 
    return new Dictionary<RegisterSection, Func<RegisterXml, RegisterGenerationArgs, Task>> 
    { 
     { RegisterSection.RegisterCover, async(reg, args) => reg.Cover = await _sectionGenerators.RegisterCoverGenerator.GenerateAsync(args) }, 
     { RegisterSection.StudentPersonalData, async(reg, args) => reg.StudentPersonalData = await _sectionGenerators.StudentPersonalDataGenerator.GenerateAsync(args)}, 

     // Add more generating here ... 
    }; 
} 

private async Task GenerateSectionsAsync(RegisterGenerationArgs args, RegisterXml reg) 
{ 
    foreach (var sectionAction in SectionActions) 
     if (SectionContainedWithin(args, sectionAction.Key)) 
      await sectionAction.Value(reg, args); 

} 
+1

ほとんどの場合、lambdaを非同期にする必要があります。 – svick

+0

@svick:そうではありません。ラムダを非同期にすることは必須ですが、辞書にはより根本的な問題があります:辞書を作成する際に 'SectionContainedWithin()'メソッドを評価すると、 'args'がその時に認識されているだけでなく、一度に2つの項目だけが辞書に登録され、そのうちの1つだけがキー値「真」を持つことになります。詳細については、私の投稿された回答を参照してください。 –

+0

@PeterDunihoあなたが正しいです、私は 'Dictionary'の問題を認識しませんでした。 – svick

答えて

1

になってしまった厥。あなたは値のペアを格納するためだけに使用しているようです。すでに知っているキー値を別の値にマップすることができる辞書の主要な機能を使用していません。

SectionContainedWithin()呼び出しを評価するために、argsの値が必要なので、提案しているコード例は機能しません。あなたはargsが有効であると辞書を初期化するために使用することができ、あなたはそれはあなたが唯一の辞書に2つのエントリを持つことができますを意味しますキータイプboolを作る問題を抱えているだろう文脈で辞書を宣言しようとしていた場合でも、多くの場合、SectionContainedWithin()メソッドが返されたすべての組み合わせを実際に処理する方法はありません。true。あなたがやっていることを明らかに示している良いMinimal, Complete, and Verifiable code exampleなし

、それはあなたが必要な正確に何を確実に知ることは不可能です。そして、あなたが何かを行うことができます

struct SectionGenerator<TArgs> 
{ 
    public readonly RegisterSection RegisterSection; 
    public readonly Func<TArgs, Task> Generate; 

    public SectionGenerator(RegisterSection registerSection, Func<TArgs, Task> generate) 
    { 
     RegisterSection = registerSection; 
     Generate = generate; 
    } 
} 

SectionGenerator<TArgs>[] generators = 
{ 
    new SectionGenerator<TArgs>(RegisterSection.StudentPersonalData, 
     async args => schoolRegister.StudentPersonalData = await _sectionGeneratorsProvider.StudentPersonalDataGenerator.GenerateAsync(args); 
    // etc. 
} 

:すべてのこれらの非同期操作が並行して進行中であるために、それは合理的だと仮定すると、

foreach (SectionGenerator<TArgs> generator in generators) 
{ 
    if (SectionContainedWithin(args, generator.RegisterSection)) 
    { 
     await generator.Generate(args); 
    } 
} 

を、あなたもこのような何かを行うことができますが、それはこのようになります。 :

await Task.WhenAll(generators 
    .Where(g => SectionContainedWithin(args, g.RegisterSection)) 
    .Select(g => g.Generate(args)); 
+0

あなたはそうです。この場合、辞書は考慮すべき最良のコレクションタイプではありません。むしろ 'IEnumerable >>'を使うか、 'bool'と' func'のペアを格納する新しい 'class'を作成します。私はそれを変えるつもりです! _MCVコードexample_の提供について、最初の解決策( 'if'sのセット)が動作し、私が想像できる最も明白なアプローチです。しかし、維持するのは難しいですが。 私はこの質問に戻ってきます。ありがとう! – pizycki

+1

@pizycki:私は 'bool'値を格納する点を理解していません。メソッド呼び出しを評価することができれば、 'args'値を得て、適切な' GenerateAsync() 'メソッドを呼び出すことができます。その場合に格納する必要があるのは、返されるタスクのみです。手元に 'args'値がない場合、' bool'値を得る方法はありません。いずれにしても、コレクションに 'bool'を格納することは意味がありません。 –

+0

あなたは正しいです、それは今も私にとっては意味がありません。これを指摘していただきありがとうございます。 – pizycki

関連する問題