Dread Boy
Dread Boy

Reputation: 722

Raise an event before anybody has subscribed to it

I would like to raise an event and notify existing subscribers if any exist. But I also expect new subscribers to be notified of all events raised so far as soon as they subscribe. Is this possible out of the box or do I need to implement that functionality myself? Right now my code look like this:

public delegate void GridCompiled(int gridsize);
public event GridCompiled OnGridCompiled;

ctor(){
    if (OnGridCompiled != null)
        OnGridCompiled(gridsize);
}

If event has 0 subscribers it won't be raised and it also won't be raised for subscribers that subscribe after event has been raised.

In case I need to implement that myself, what are my options?

Upvotes: 3

Views: 411

Answers (1)

Sefe
Sefe

Reputation: 14007

There is no tracking of raising events, so you would have to implement the functionality yourself. You would need a list to store your previous event arguments in order and execute the related events when a new event listener is added:

class Example {
    private readonly List<GridCompiledEventArgs> m_previousEventArgs = new List<EventArgs>();
    private EventHandler<GridCompiledEventArgs> m_gridCompiled;

    public event EventHandler<GridCompiledEventArgs> GridCompiled {
        add {
            //Raise previous events for the caller
            foreach(GridCompiledEventArgs e in m_previousEventArgs) {
                value(this, e);
            }
            //Add the event handler
            m_gridCompiled += value;
        }
        remove {
            m_gridCompiled -= value;
        }
    }

    protected virtual void OnGridCompiled(GridCompiledEventArgs e) {
        if (m_gridCompiled != null) {
            m_gridCompiled(this, e);
        }
        m_previousEventArgs.Add(e);
    }
}

There are two things you have consider for this solution. If you want to adress them, your solution will become more complex:

  1. If GridCompiledEventArgs can be changed by an event handler (e.g. to return a status to the caller), the event args will be stored in the previous event list with those changes. Also, if an event handler keeps a reference to the event args they might even change it later. If you don't want that, you have to store a copy in m_previousEventArgs and create another copy before you raise the "historic" event.
  2. It is best practice to allow derived classes to override the OnGridCompiled method instead of handling the event or changing its behavior. If a derived class changes OnGridCompiled to intercept the event and not raise it in certain cases, this behavior will not always apply for the "historic" event, since it is raised without OnGridCompiled (which might be just the behavior you want). If you want to change that you have to implement a solution that goes through OnGridCompiled. If this is an option for you, you can avoid this problem by making the class sealed and the OnGridCompiled method private instead of protected virtual.

Upvotes: 5

Related Questions