Reputation: 722
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
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:
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.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