Search code examples
c#.netobserver-pattern

Observer pattern with delegate and events using an event array


We have a class which manages many queues that store data. I want a user to get notified when new data is added to each of these queues. I'd like to use the observer pattern using delegate and events. Normally for a single event and source, we'd do:

public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate NewDataAdded;

and for the observer:

qManager.NewDataAdded += new qManager.NewDataAddedDelegate(getNewDataFunc);

But in this case, we have, say, 10 queues, each of which can receive data arbitrarily. So we'd like the observer functions to subscribe to an individual queue. We thought we could do:

public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate [] NewDataAdded;  // can't do this

and in the constructor of qManager:

NewDataAdded = new NewDataAddedDelegate[numberOfQueues];

and in the observer:

qManager.NewDataAdded[0] += new qManager.NewDataAddedDelegate(getNewDataFunc0);
qManager.NewDataAdded[1] += new qManager.NewDataAddedDelegate(getNewDataFunc1);

but no go, since the event is expected to be a delegate type, not an array of delegates type.

Any ideas on how to approach this problem?


Solution

  • No, events don't work like that. Options:

    • Create another type which exposes the event, and have an array or collection of that type:

      // Preferably *don't* just expose an array...
      public TypeWithEvent[] Queues { get { ... } }
      
      // Subscription:
      qManager.Queues[i].NewDataAdded += ...
      
    • Alternatively, don't use events, and just have a method:

      private NewDataAddededDelegate[] newDataAdded;
      
      public void SubscribeNewDataAddedHandler(int queue, 
                                               NewDataAddedDelegate handler)
      {
          newDataAdded[queue] += handler;
      }
      
      // Subscription
      qManager.SubscribeNewDataAddedHandler(0, ...);
      

    Personally it sounds to me like each queue should really be its own object though... make the queue manager exposes a collection of queues, each of which can be subscribed to individually. (i.e. take the first approach.) Otherwise your queue manager is really doing too much work.