如何在 C# 中引用事件 [英] How to reference an event in C#
问题描述
我有以下课程,其中有一个名为 LengthChanged
的公共事件:
I have the following class, which has one public event called 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
类一无所知.我想出了两个方案,但没有一个是真正令人满意的:
I would like to be able to register/unregister handlers for this event in a method called Observer
, which does not know anything about the Dimension
class. I have come up with two scenarios, none of which are really satisfying:
使用
LengthChanged
事件定义接口ILengthChanged
,然后确保Dimension
实现ILengthChanged
.然后我必须为我定义的每个接口提供一个Observer
方法的实现.这绝对不够通用.我真的希望能够简单地传递对System.EventHandler
事件的引用.
Define an interface
ILengthChanged
with theLengthChanged
event, then make sureDimension
implementsILengthChanged
. Then I have to provide one implementation of theObserver
method for every interface I define. This by no way generic enough. I'd really want to be able to simply pass in a reference to aSystem.EventHandler
event.
使用System.Action
回调在Observer
方法中注册和注销事件处理程序,就像这样:
Use System.Action<System.EventHandler>
callbacks for registering and unregistering the event handler in the Observer
method, just like that:
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);
并且当它被执行时,确实最终会将 LengthChanged
事件与内部事件处理程序 MyEventHandler
连接起来.但这不是很优雅.我很想能够写这个:
and which, when executed, will indeed end up wiring the LengthChanged
event with the internal event handler MyEventHandler
. But this is not very elegant. I would have loved to be able to write this instead:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged);
但我不知道如何实现.也许我在这里遗漏了一些非常明显的东西?我想一些 dynamic
魔法可以以某种方式解决问题,但这不会强制编译时类型检查:我不希望 Observer
的用户传入对不满足 System.EventHandler
事件签名的事件的引用.
but I've no idea how this could be achieved. Maybe I am missing something really obvious here? I guess that some dynamic
magic could do the trick, somehow, but this would not enforce compile-time type checking: I don't want the users of Observer
to pass in references to events which do not satisfy the System.EventHandler
event signature.
推荐答案
不幸的是,没有真正的方法可以做到这一点.事件通常不是 .NET 中的一等公民 - 尽管 F# 试图在那里推广它们.
Unfortunately there isn't really a way of doing this. Events aren't first class citizens in .NET in general - although F# tries to promote them there.
要么传入订阅/取消订阅委托,要么使用指示事件名称的字符串.(后者通常更短,但在编译时显然不太安全.)
Either pass in the subscribe/unsubscribe delegate or using a string indicating the name of the event. (The latter is often shorter, but obviously less safe at compile-time.)
那些是 Reactive Extensions 采用的方法 - 如果有更清洁的这样做的方式,我相信他们会使用它:(
Those are the approaches which Reactive Extensions takes - if there were a cleaner way of doing it, I'm sure they would be using that :(
这篇关于如何在 C# 中引用事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!