如何在C#中引用事件

Pie*_*aud 7 c# events reference callback event-handling

我有以下类,它有一个名为的公共事件LengthChanged:

class Dimension
{
    public int Length
    {
        get
        {
            return this.length;
        }
        set
        {
            if (this.length != value)
            {
                this.length = value;
                this.OnLengthChanged ();
            }
    }

    protected virtual void OnLengthChanged()
    {
        var handler = this.LengthChanged;
        if (handler != null)
        {
            handler (this, System.EventArgs.Empty);
        }
    }

    public event System.EventHandler LengthChanged;

    private int length;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够在一个名为的方法中注册/取消注册此事件的处理程序,该方法Observer对该Dimension类一无所知.我想出了两个场景,其中没有一个真的令人满意:

  1. 定义一个接口ILengthChangedLengthChanged事件,然后确保Dimension器具ILengthChanged.然后我必须为Observer我定义的每个接口提供该方法的一个实现.这绝不是通用的.我真的希望能够简单地传递对System.EventHandler事件的引用.

  2. 使用System.Action<System.EventHandler>回调来注册和取消注册方法中的事件处理程序Observer,就像这样:

    class Foo {public void Observer(System.Action register,System.Action unregister){register(this.MyEventHandler);

        // keep track of the unregister callback, so that we can unregister
        // our event handler later on, if needed...
    }
    
    private void MyEventHandler(object sender, System.EventArgs e)
    {
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    }

然后会像这样调用:

Foo foo = ...;
Dimension dim = ...;

foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);
Run Code Online (Sandbox Code Playgroud)

并且在执行时,最终将LengthChanged使用内部事件处理程序连接事件MyEventHandler.但这不是很优雅.我本来希望能够写下这个:

Foo foo = ...;
Dimension dim = ...;

foo.Observer (dim.LengthChanged);
Run Code Online (Sandbox Code Playgroud)

但我不知道如何实现这一目标.也许我错过了一些非常明显的东西?我想有些dynamic魔术可以做到这一点,不知何故,但这不会强制执行编译时类型检查:我不希望用户Observer传入对不满足System.EventHandler事件签名的事件的引用.

Jon*_*eet 10

不幸的是,没有办法做到这一点.事件通常不是.NET中的一等公民 - 尽管F#试图在那里推广它们.

传入subscribe/unsubscribe代理或使用指示事件名称的字符串.(后者通常较短,但在编译时显然不太安全.)

这些是Reactive Extensions采用的方法- 如果有更简洁的方法,我相信他们会使用它:(