泡沫事件的首选方式是什么?

我有三个对象,ObjectA有一个ObjectB,ObjectB有一个ObjectC。 当ObjectC触发事件时,我需要ObjectA来了解它,所以这就是我所做的……

public delegate void EventFiredEventHandler(); public class ObjectA { ObjectB objB; public ObjectA() { objB = new ObjectB(); objB.EventFired += new EventFiredEventHandler(objB_EventFired); } private void objB_EventFired() { //Handle the event. } } public class ObjectB { ObjectC objC; public ObjectB() { objC = new ObjectC(); objC.EventFired += new EventFiredEventHandler(objC_EventFired); objC.FireEvent(); } public event EventFiredEventHandler EventFired; protected void OnEventFired() { if(EventFired != null) { EventFired(); } } private void objC_EventFired() { //objC fired an event, bubble it up. OnEventFired(); } } public class ObjectC { public ObjectC(){} public void FireEvent() { OnEventFired(); } public event EventFiredEventHandler EventFired; protected void OnEventFired() { if(EventFired != null) { EventFired(); } } } 

这是处理这个问题的正确方法,还是有更好的方法? 我不希望ObjectA完全了解ObjectC,只是它引发了一个事件。

另一种方法是使用add / remove包装它:

 public class ObjectB { ObjectC objC; public ObjectB() { objC = new ObjectC(); } public event EventFiredEventHandler EventFired { add { this.objC.EventFired += value; } remove { this.objC.EventFired -= value; } } } 

这就是我这样做的方式。 但是,我建议将你的发射机制改为此,以使其线程安全

 protected void OnEventFired() { var tmpEvent = EventFired; if(tmpEvent != null) { tmpEvent(); } } 

如果在空检查和触发之间EventFired变为null,这可以防止它失败。

对于您的事件委托,遵循EventHandler模​​式也是一种标准。

 protected virtual void OnEventFired(EventArgs e) { var tmpEvent = EventFired; if(tmpEvent != null) { tmpEvent(this, EventArgs.e); } } 

我对线程安全模式错了,这里是完整的线程安全事件模式

 ///  /// Delegate backing the SomeEvent event. ///  SomeEventHandler someEvent; ///  /// Lock for SomeEvent delegate access. ///  readonly object someEventLock = new object(); ///  /// Description for the event ///  public event SomeEventHandler SomeEvent { add { lock (someEventLock) { someEvent += value; } } remove { lock (someEventLock) { someEvent -= value; } } } ///  /// Raises the SomeEvent event ///  protected virtual OnSomeEvent(EventArgs e) { SomeEventHandler handler; lock (someEventLock) { handler = someEvent; } if (handler != null) { handler (this, e); } } 

正如其他答案所述,这是他们做到这一点的方法。

但你可以超越!!! 我刚刚在它上面实现了一个很好的数据结构,它就像是给你一个旋转。

有一个自动事件冒泡会很高兴吗? 您可以使用Reflection实现它。 我的方法是定义一个Interface / Base类,它声明一个事件(或一组事件)。 然后,基类的无参数构造函数将迭代其他属性/字段,并自动注册成员事件以进行事件传播。

设计有一些限制,但如果你有一个深层结构和/或许多(结构化)事件,那么在没有任何额外代码行的情况下完成所有设置可能会很不错。

初始基类可以是:

 class BaseObject { public BaseObject() { FieldInfo[] fInfos = this.GetType().GetFields(...); foreach (FieldInfo fInfo in fInfos) { object fInfoValue = fInfo.GetValue(this, null); if (fInfoValue is BaseObject) { BaseObject bMemberObject = (BaseObject)fInfoValue; bMemberObject.MyEvent += new EventHandler(delegate() { if (this.MyEvent != null) MyEvent(); }); } } public event MyEvent = null; } 

当然,正如已经建议的那样,遵循事件委托委托(object sender,EventArgs args) (为了清楚起见,我使用了一个更简单的事件)。 当然,隐含的是您的类ABC直接从BaseObject派生。

请注意,可以实现任何逻辑来绑定结构化事件(您可以使用名称和/或其他reflection属性进行嵌套事件注册。