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

Tes*_*101 16 c# events event-bubbling

我有三个对象,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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

BFr*_*ree 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; }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sco*_*ain 5

我就是这样做的。但是我建议将您的触发机制更改为此以使其线程安全

protected void OnEventFired()
{
    var tmpEvent = EventFired;
    if(tmpEvent != null)
    {
        tmpEvent();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

此外,遵循事件委托的EventHandler 模式也是一种标准。

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

我对线程安全模式的看法是错误的,这是完整的线程安全事件模式

/// <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);
    }
}
Run Code Online (Sandbox Code Playgroud)