2016-08-02 5 views
0

나는 모든 GenerateAsync는 다른 유형의 객체를 생성이비동기 메서드 호출을 사용하여 조건 집합을 사전으로 변환하려면 어떻게해야합니까?

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의를 다시 작성할 수 있습니다. 뭔가 같은 :

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(); 
    } 
} 

해결책 :

덕분에 내가 Dictionary<bool, Func<Task>>을 만드는 아이디어를 떨어 뜨 더 의미가 있기 때문에 IReadOnlyDictionary<RegisterSection, Func<RegisterXml, RegisterGenerationArgs, Task>>로 대체 @ 피터 duniho의 대답. 두 개의 true/false뿐만 아니라 여러 개의 키. 내가 제대로 코드 예제를 이해한다면

그래서 사전 정말이 작업에 적합한 도구가 아닙니다, 나는

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

거의 다 왔으므로 람다를 '비동기'로 만들어야합니다. – svick

+0

@svick :별로 없습니다. 람다를 async로 만드는 것은 필수적이지만, 사전에 더 근본적인 문제가 있습니다 : 사전을 채울 때'SectionContainedWithin()'메소드를 평가하는 것은'args'가 그 시간에 알려졌다는 것을 가정 할뿐만 아니라, 한 번에 두 개의 항목 만 사전에 포함되며 그 중 하나만 핵심 값인 '참'을 갖습니다. 자세한 내용은 내 게시 된 답변을 참조하십시오. –

+0

@PeterDuniho 네가 맞아, 나는 '사전'문제를 알지 못했다. – svick

답변

1

으로 결국 무엇을 이잖아. 당신은 값 쌍을 저장하기 위해서만 사용하는 것처럼 보입니다. 이미 알고있는 키 값을 다른 값에 매핑 할 수있는 사전의 기본 기능을 사용하지 않습니다.

또한 SectionContainedWithin() 호출을 평가하기 위해 args 값이 필요하므로 제안한 코드 예제가 작동하지 않습니다. 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 >>'을 사용하거나'bool'과'func' 쌍을 저장하기 위해 새로운'class'를 생성 할 것입니다. 나는 그것을 바꿀거야! _MCV 코드 example_를 제공하는 것에 대해 첫 번째 솔루션 ('if's 세트)이 작동하며 내가 상상할 수있는 가장 확실한 접근 방식입니다. 알기 힘든 일이지만 나는이 질문에 다시 올 것이다. 감사! – pizycki

+1

@pizycki : 나는 'bool'값을 저장한다는 요지를 이해하지 못합니다. 메소드 호출을 평가할 수 있다면,'args' 값을 얻었고 적절한'GenerateAsync()'메소드를 호출 할 수 있습니다. 이 경우 저장해야하는 것은 반환 된 작업뿐입니다. 'args' 값을 가지고 있지 않다면'bool' 값을 얻을 방법이 없습니다. 어쨌든, 컬렉션에'bool'을 저장하는 것은 말이되지 않습니다. –

+0

네 말이 맞아, 나도 마찬가지야. 이것을 지적 해 주셔서 감사합니다. – pizycki

관련 문제