如何在C#中引用事件

问题描述 投票:7回答:3

我有以下课程,有一个名为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;
}

我希望能够在名为Observer的方法中注册/注销该事件的处理程序,该方法对Dimension类一无所知。我提出了两种情况,但没有一种能真正令人满意:

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

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

    Foo类{公共无效的观察者(System.Action寄存器,System.Action取消注册){注册(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)
    {
        ...
    }
    

    }

然后将这样调用:

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

foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);

并且在执行时确实会最终将LengthChanged事件与内部事件处理程序MyEventHandler进行连接。但这不是很优雅。我本来希望能够写成这样:

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

foo.Observer (dim.LengthChanged);

但是我不知道如何实现。也许我在这里错过了一些明显的东西?我猜想某些dynamic魔术可以某种方式解决问题,但这不会强制执行编译时类型检查:我不希望Observer的用户传递对不满足System.EventHandler的事件的引用]事件签名。

c# events reference callback event-handling
3个回答
10
投票

不幸的是,实际上没有办法。一般而言,事件不是.NET中的头等公民-尽管F#试图在那里推广事件。

要么通过订阅/取消订阅委托,要么使用表示事件名称的字符串。 (后者通常更短,但显然在编译时不太安全。)

[这些是Reactive Extensions所采用的方法-如果有更清洁的方法,我敢肯定他们会使用:(


2
投票

不应将事件传递给另一个方法。但是,您可以将委托传递给另一个方法。也许,您正在寻找的只是一个简单的公共代表而不是事件。

如果您将活动更改为此]

public System.EventHandler LengthChanged; 

您可以像这样简单地将LengthChanged传递给Observer

Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged); 

1
投票

您可以创建自定义访问器。

© www.soinside.com 2019 - 2024. All rights reserved.