2011-01-21 43 views
7

我有下面的类,它有一个公共事件调用LengthChanged如何引用在C#中的事件

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. 定义的接口ILengthChangedLengthChanged事件,然后确保Dimension实现ILengthChanged。然后,我必须为我定义的每个接口提供一个Observer方法的实现。这绝不够通用。我真的希望能够简单地传递对System.EventHandler事件的引用。

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

    类Foo { 公共无效观察员(System.Action寄存器, System.Action注销) { 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事件签名的事件。

回答

10

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

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

这些是Reactive Extensions需要采取的方法 - 如果有更干净的方法,我肯定他们会使用那个:(

+0

如果人们像埃里克·梅杰没能拿出更清洁的解决方案,我怀疑事实上,没有其他办法可以做到这一点。很伤心......谢谢你的快速回复,Jon。 – 2011-01-21 09:09:48

2

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

如果您的事件改变这个

public System.EventHandler LengthChanged; 

你可以简单地通过LengthChanged来观察这样

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

谢谢你的建议。不,我不能通过代表而不是事件;该事件可能会实现`add`和`remove`设置器,而且必须被定义为一个完整的C#`事件`。 – 2011-01-21 09:07:38

相关问题