2014-02-17 4 views
-2

그래서 나는 다음과 같습니다일반 대리인 EndInvoke를 만드는 방법은 무엇입니까?

private delegate Foo1 GetFooAsync1(Foo1 foo1); 
private delegate Foo2 GetFooAsync2(Foo2 foo2); 
private delegate Foo3 GetFooAsync3(Foo3 foo3); 
private delegate Foo4 GetFooAsync4(Foo4 foo4); 

private FooAsync1 foo1; 
private FooAsync2 foo2; 
private FooAsync3 foo3; 
private FooAsync4 foo4; 

그리고리스트에 계속적으로 간다, 나는 가끔 예외를 던져 않기 때문에, 각 EndInvoke에 시도 캐치를 넣어 싶지 않아하는 방법 내부 그러나 그것을 시스템을 멈추지 말고 다른 Foos를 계속해서는 안된다. 그리고 만약 각각의 Foos를 잡으려고한다면, 너무 많은 공간을 차지한다.

최종 호출을 호출하는 일반적인 방법으로 이 있습니까? 그래서 예상 결과를 얻을 수 있습니까?

var result1 = foo1.EndInvoke(fooIAsyncResult); 
+0

이 두 biltin delegeates는 .NET Func을 에 있고 액션 당신은 람다 식을 전달할 수는 90 %의 시나리오 – Developerzzz

+0

를 덮고 사용 http://stackoverflow.com/questions/14297633/c-sharp- pass-lambda-expression-as-method-parameter –

+0

대리자를 매개 변수로 사용하는 대리자를 작성하는 이유를 이해할 수 없습니다. 이런 종류의 중첩이없는 솔루션을 작성했습니다. 도움이되지 않으면 예제를 실제 코드로 바꿉니다. –

답변

0

일반적인 방법이를 달성하기 위해,이 같은 EndInvoke을 무시 확장 메서드를 선언해야 할 것 :

public static class DelegateExtensions 
{ 
    public static TResult EndInvoke<TDelegate, TResult>(this TDelegate asyncCaller, IAsyncResult asyncResult) where TDelegate : System.Delegate 
    { 
     TResult result = default(TResult); 

     try 
     { 
      result = asyncCaller.EndInvoke(asyncResult); 
     } 
     catch (Exception ex) 
     { 
      LogExceptionMessageOrWhatever(ex.Message); 
      throw; 
     } 

     return result; 
    } 
} 

그러나, 그 절차는 컴파일러 오류가 발생합니다. 왜? System.Delegate 클래스는 제네릭 제약 조건에서 사용할 수없는 특수 클래스입니다.

제약 조건을 제거하고 리플렉션을 사용하여 올바른 절차를 호출 할 수는 없습니까?

당신은 할 수 있다고 생각하지만, 제네릭 사용의 목적을 상실합니다. 더 나은 해결책은 당신의 델리게이트를 generic으로 만든 다음 그 델리게이트 만 대상으로 확장 메소드를 다시 작성하는 것입니다.

public delegate TFooResult GetFooAsync<TFooResult>(); 

public static class GetFooAsyncExtensions 
{ 
    public static TFooResult EndInvoke<TFooResult>(this GetFooAsync<TFooResult> asyncCaller, IAsyncResult asyncResult) 
    { 
     TFooResult result = default(TFooResult); 

     try 
     { 
      result = asyncCaller.EndInvoke(asyncResult); 
     } 
     catch (Exception ex) 
     { 
      LogExceptionMessageOrWhatever(ex.Message); 
      throw; 
     } 

     return result; 
    } 
} 

이제 평소와 같이 EndInvoke을 부르면됩니다. 프레임 워크는 자동으로 귀하의 버전을 사용합니다.

private void Main() 
{ 
    Foo1Result foo1 = null; 

    var foo1Factory = new GetFooAsync<Foo1Result>(
     () => 
     { 
      return new Foo1Result(); 
     }); 


    foo1Factory.BeginInvoke(
     callback: asyncResult => 
      { 
       foo1 = foo1Factory.EndInvoke(asyncResult); 
      }, 
      @object: null); 
} 
관련 문제