2016-08-02 57 views
0

我有一些方法调用看起来像这样如何将async方法调用条件转换为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 ... 

GenerateAsync产生不同类型的对象。

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

我如何重写这些if这么我可以定义的动作和条件的列表,然后遍历它们。 喜欢的东西:

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:

感谢@彼得 - duniho回答我放弃了创造Dictionary<bool, Func<Task>>的想法,因为它更有意义与IReadOnlyDictionary<RegisterSection, Func<RegisterXml, RegisterGenerationArgs, Task>>取而代之。 多个键,不仅有两个真/假。

所以,这就是我结束了

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'async'。 – svick

+0

@svick:不是。确实需要使用lambda'async',但字典中存在更多基本问题:在填充字典时评估“SectionContainedWithin()”方法不仅假定当时已知“args”,而且一次只有两件物品会出现在字典中,其中只有一件物品的关键值为“真”。查看我发布的答案,了解更多细节。 –

+0

@PeterDuniho你说得对,我没有意识到'Dictionary'问题。 – svick

回答

1

如果我理解正确的代码示例中,一本字典真的不是这个工作的工具。您似乎只用它来存储值对;您没有使用字典的主要功能,它可以将您已知的键值映射到另一个值。

此外,您提出的代码示例将不起作用,因为您需要args值才能评估SectionContainedWithin()调用。即使您尝试在args有效并且可用于初始化字典的上下文中声明字典,您也会遇到问题,即它使密钥类型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 >>或创建新的'class'来存储'bool'和'func'对。我要改变它! 关于提供_MCV代码example_,第一个解决方案(“if”集合)起作用,并且是我能想象到的最明显的方法。尽管这很难维护。 我会回到这个问题tomorow。谢谢! – pizycki

+1

@pizycki:我不明白存储'bool'值的重点。如果你能够评估方法调用,那么你已经掌握了'args'的值,并且可以继续并调用适当的'GenerateAsync()'方法。在这种情况下,您唯一需要存储的就是返回的任务。如果你手头没有'args'值,那么就无法获得'bool'值。无论哪种方式,在你的收藏中存储'bool'都没有意义。 –

+0

你说得对,现在对我来说毫无意义。感谢您指出这一点。 – pizycki

相关问题