我想提出一个事件并通知现有订阅者(如果存在)。但我也希望新订阅者能够在订阅后立即通知他们所提出的所有事件。这是开箱即用还是我需要自己实现这个功能?现在我的代码看起来像这样:
public delegate void GridCompiled(int gridsize);
public event GridCompiled OnGridCompiled;
ctor(){
if (OnGridCompiled != null)
OnGridCompiled(gridsize);
}
如果活动有0个订阅者,则不会被提出,并且在活动被提出后订阅的订阅者也不会被提出。
如果我需要自己实施,我的选择是什么?
答案 0 :(得分:5)
没有跟踪引发事件,因此您必须自己实现这些功能。您需要一个列表来按顺序存储您之前的事件参数,并在添加新事件侦听器时执行相关事件:
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);
}
}
您已为此解决方案考虑了两件事。如果您想要解决这些问题,您的解决方案将变得更加复杂:
GridCompiledEventArgs
(例如,将状态返回给调用者),则事件args将与这些更改一起存储在上一个事件列表中。此外,如果事件处理程序保留对事件args的引用,它们甚至可能在以后更改它。如果您不想这样,则必须在m_previousEventArgs
中存储副本并在发起“历史性”事件之前创建另一个副本。OnGridCompiled
方法,而不是处理事件或更改其行为。如果派生类更改OnGridCompiled
以拦截事件而在某些情况下不提升它,则此行为将不会始终适用于“历史”事件,因为它是在没有OnGridCompiled
的情况下引发的(可能只是你想要的行为)。如果要更改,则必须实施通过OnGridCompiled
的解决方案。如果这是您的选项,则可以通过制作课程sealed
和OnGridCompiled
方法private
而非protected virtual
来避免此问题。