-2

だから私は次のものを持っています:

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 に try catch を配置したくありません。例外をスローすることもありますが、システムを停止してはならず、他の Foos を続行する必要があるためです。そして、それぞれに try キャッチがある場合、メソッド内で非常に多くのスペースを占有します。

end invoke を呼び出す一般的な方法はありますか? それで、期待される結果を返すことができますか?

var result1 = foo1.EndInvoke(fooIAsyncResult);
4

1 に答える 1

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);
}
于 2014-02-17T10:31:40.630 に答える