我有三个对象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,只是它引发了一个事件。
答案 0 :(得分:20)
另一种方法是使用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; }
}
}
答案 1 :(得分:3)
这就是我这样做的方式。但我建议将你的发射机制更改为使其线程安全
protected void OnEventFired()
{
var tmpEvent = EventFired;
if(tmpEvent != null)
{
tmpEvent();
}
}
如果EventFired在空检查和触发之间变为空,这可以防止它失败。
对于您的活动代表来说,遵循EventHandler pattern也是一种标准。
protected virtual void OnEventFired(EventArgs e)
{
var tmpEvent = EventFired;
if(tmpEvent != null)
{
tmpEvent(this, EventArgs.e);
}
}
我对线程安全模式错了,这里是完整的线程安全事件模式
/// <summary>
/// Delegate backing the SomeEvent event.
/// </summary>
SomeEventHandler someEvent;
/// <summary>
/// Lock for SomeEvent delegate access.
/// </summary>
readonly object someEventLock = new object();
/// <summary>
/// Description for the event
/// </summary>
public event SomeEventHandler SomeEvent
{
add
{
lock (someEventLock)
{
someEvent += value;
}
}
remove
{
lock (someEventLock)
{
someEvent -= value;
}
}
}
/// <summary>
/// Raises the SomeEvent event
/// </summary>
protected virtual OnSomeEvent(EventArgs e)
{
SomeEventHandler handler;
lock (someEventLock)
{
handler = someEvent;
}
if (handler != null)
{
handler (this, e);
}
}
答案 2 :(得分:1)
正如其他答案所述,这是他们的方法。
但你可以超越!!!我刚刚在它上面实现了一个很好的数据结构,它就像是给你一个旋转。
自动事件冒泡会不会很好?您可以使用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)(为了清楚起见,我使用了一个更简单的事件)。 当然,隐含的是您的类 A , B 和 C 直接从 BaseObject 派生。
请注意,可以实现任何逻辑来绑定结构化事件(您可以使用名称和/或其他反射属性进行嵌套事件注册。