MulticastDelegate和Exception处理:是否可以将它全部包装起来?

use*_*291 3 .net c#

在调用多播委托时,应该使用GetInvocationList逐个调用委托:

public void IterateAll()
{
    if( _doExecute != null )
    {
        foreach( ExecuteCallback doSingleExecute in _doExecute.GetInvocationList() )
        {
            try
            {
                doSingleExecute();
            }
            catch
            {
                // This delegate threw an exception
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有一种方法可以对此进行泛化,以便通过包装此迭代来回到单个调用以隐藏它,以便可以再次调用整个多播委托?这将更接近故意水平.

cdh*_*wie 6

你可以这样做:

public static void CallAllAndCatch(this Action self)
{
    if (self == null)
        return;

    foreach (Action i in self.GetInvocationList()) {
        try { i(); }
        catch { }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果你发现自己这么做很多,你可以使用泛型EventHandler<T>,但是对于任何类型的任何委托你都不能这样做,因为委托类型不能在彼此之间分配,即使它们是兼容的,也没有机制定义通用方法以将特定泛型参数限制为具有特定签名的委托时.(我认为具有相同签名的代理被认为是以.NET 4开头的兼容类型.)

对于EventHandler<T>方法:

public static void CallAllAndCatch(this EventHandler<T> self, object sender, T args)
    where T : EventArgs
{
    if (self == null)
        return;

    foreach (EventHandler<T> i in self.GetInvocationList()) {
        try { i(sender, args); }
        catch { }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你不介意抛出性能和编译时类型检查管,你可以这样做,这将适用于任何委托类型:

public static void CallAllAndCatch(this Delegate self, params object[] args)
    where T : EventArgs
{
    if (self == null)
        return;

    foreach (Delegate i in self.GetInvocationList()) {
        try { i.DynamicInvoke(args); }
        catch (MemberAccessException) { throw; } // A type of something in args isn't compatible with the delegate signature.
        catch (TargetException) { throw; } // The delegate itself is invalid.
        catch { } // Catch everything else.
    }
}
Run Code Online (Sandbox Code Playgroud)