Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MulticastDelegate and Exception handling: is it possible to wrap it all generically?

Tags:

c#

.net

When calling a Multicast Delegate one should use GetInvocationList to call one by one the delegate:

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

Is there a way to genericize this so as to go back to one single call by wrapping this iteration so as to hide it and so that one could call only once again the whole multicast delegate ? This would be closer to the intentional level.

like image 296
user310291 Avatar asked Jan 24 '26 06:01

user310291


1 Answers

You could do something like this:

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

    foreach (Action i in self.GetInvocationList()) {
        try { i(); }
        catch { }
    }
}

Note that you can use generics if you find yourself doing this a lot with e.g. EventHandler<T>, but you cannot do this generically for any delegate of any type since delegate types cannot be assigned between each other, even if they are compatible, and there is no mechanism when defining a generic method to restrict a specific generic parameter to be a delegate with a specific signature. (I think delegates with identical signatures are considered compatible types starting with .NET 4.)

For the EventHandler<T> approach:

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 { }
    }
}

If you don't mind throwing performance and compile-time type checking down the tube, you can do this, which will work with any delegate type:

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.
    }
}
like image 134
cdhowie Avatar answered Jan 26 '26 19:01

cdhowie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!