2014-02-17 62 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 ..並佔用這麼多的方法空間,如果每個人都試圖抓住它。

是否有通用方式來調用結束調用?所以我可以返回預期的結果?

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

有兩個biltin delegeates在.NET函數功能和行動使用它,它覆蓋90%的情況下 – Developerzzz

+0

你可以傳遞一個lambda表達式 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類是不能在通用約束中使用的特殊類。

所以你不能只是擺脫約束,並使用反射來調用正確的過程?

我想你可以,但是這打破了使用泛型的目的。更好的解決方案是使您的委託通用,然後重寫擴展方法以僅定位該委託。

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