これを一般的な方法で実現するには、次の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);
}