Search code examples
c#eventsdelegatesmulticastdelegate

Using MulticastDelegate as parameter while avoiding DynamicInvoke


I have a MulticastDelegate that can reference one of a number of (legacy) delegates that have the same signature. For example:

public delegate void ObjectCreated(object sender, EventArgs args);
public delegate void ObjectDeleted(object sender, EventArgs args);
//...

Those delegates are then used to define events:

public event ObjectCreated ObjectWasCreated;
public event ObjectDeleted ObjectWasDeleted;

I then have a method which takes in a MulticastDelegate that I use to do some common checking:

void DispatchEvent(MulticastDelegate handler, object sender, EventArgs args)
{
    if (handler != null)
    {
        // ...
        handler.DynamicInvoke(sender, args);
    }
}

Which is called from within other methods of the class wherein the events were defined:

DispatchEvent(ObjectWasCreated, sender, args);
DispatchEvent(ObjectWasDeleted, sender, args);

Is there a more concise way to do this that avoids DynamicInvoke?


Solution

  • Here's my reflection-free solution. It basically implements a multicast delegate as a list. Less code? No. Better performance? I don't know. Cleaner? Meh.

    public delegate void ObjectCreated(object sender, EventArgs args);
    public delegate void ObjectDeleted(object sender, EventArgs args);
    
    public event ObjectCreated ObjectWasCreated
    {
        add
        {
            m_ObjectCreatedSubscribers.Add(value.Invoke);
        }
        remove
        {
            m_ObjectCreatedSubscribers.RemoveAll(e => e.Target.Equals(value));
        }
    }
    public event ObjectDeleted ObjectWasDeleted
    {
        add
        {
            m_ObjectDeletedSubscribers.Add(value.Invoke);
        }
        remove
        {
            m_ObjectDeletedSubscribers.RemoveAll(e => e.Target.Equals(value));
        }
    }
    
    private List<Action<object, EventArgs>> m_ObjectCreatedSubscribers = new List<Action<object, EventArgs>>();
    private List<Action<object, EventArgs>> m_ObjectDeletedSubscribers = new List<Action<object, EventArgs>>();
    
    void DispatchEvent(List<Action<object, EventArgs>> subscribers, object sender, EventArgs args)
    {
        foreach (var subscriber in subscribers)
            subscriber(sender, args);
    }