如何使一个泛型委托EndInvoke? [英] How to make a generic delegate EndInvoke?

查看:151
本文介绍了如何使一个泛型委托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 ..并占用了太多的空间,如果每个人都尝试捕捉它。

And the lists goes on and on, then inside a method I don't want to put a try catch on each EndInvoke, because sometimes it does throw an exception but it shouldn't stop the system, and continue with the other Foos.. And takes up so much space in the method if each had a try catch around it.

是否有一种通用方式来调用end invoke?所以我可以返回预期的结果?

Is there a generic way to call end invoke? So I can return the expected result?

var result1 = foo1.EndInvoke(fooIAsyncResult);


推荐答案

为了以通用的方式实现这一点,你'需要声明一个扩展方法,覆盖 EndInvoke ,如下所示:

In order to achieve this in a generic way, you'd need to declare an extension method that overrides EndInvoke like this:

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 类是一个不能用于通用约束的特殊类。

However, that procedure will generate a compiler error. Why? The System.Delegate class is a special class that cannot be used in generic constraints.

那么你不能只是摆脱了约束,并使用反射来调用正确的过程?

So can't you just get rid of the constraint, and use reflection to invoke the right procedure?

我想你可以,但是这违背了使用泛型的目的。一个更好的解决方案是让你的委托通用,然后重写扩展方法来仅定向委托。

I suppose you could, but that defeats the purpose of using generics. A better solution would be to make your delegate generic, then rewrite the extension method to target only that 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 像你通常会这样。框架将自动使用您的版本。

Now you'd call EndInvoke like you normally would. The framework will automatically use your version.

private void Main()
{
    Foo1Result foo1 = null;

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


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

这篇关于如何使一个泛型委托EndInvoke?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆