我有以下这个类,其中有一个名为
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
类的任何信息。我想出了两种方案,但都不是很令人满意:
定义一个带有
LengthChanged
事件的接口ILengthChanged
,然后确保Dimension
实现了ILengthChanged
。然后,我必须为我定义的每个接口提供一个Observer
方法的实现。这远远不够通用。我真的希望能够简单地传递一个对System.EventHandler
事件的引用。在
Observer
方法中使用System.Action<System.EventHandler>
回调来注册和取消注册事件处理程序,就像这样:
class Foo
{
public void Observer(System.Action<System.EventHandler> register,
System.Action<System.EventHandler> 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)
{
...
}
}
然后可以像这样调用:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);
执行后,将确实使用内部事件处理程序MyEventHandler
连接LengthChanged
事件。但这并不是很优雅。我希望能够写成:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged);
但我不知道如何实现。也许我在这里漏掉了一些非常明显的东西?我猜想一些 dynamic
魔法可以以某种方式解决问题,但这将不会强制进行编译时类型检查:我不希望 Observer
的使用者传递不符合 System.EventHandler
事件签名的事件引用。