如何引用C#中的事件 [英] How to reference an event in C#

查看:153
本文介绍了如何引用C#中的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类,其中有一个公共事件 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 implements ILengthChanged 。然后,我必须为我定义的每个接口提供 Observer 方法的一个实现。这没有通用的。我真的希望能够简单地传递一个 System.EventHandler 事件的引用。


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



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

      //跟踪取消注册回调,可以注销
    //稍后我们的事件处理程序,如果需要...
    }

    private void MyEventHandler(object sender,System.EventArgs e)
    {
    ...
    }

    }

    b $ b

这样调用:

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

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

,并且当执行时,确实会结束 LengthChanged 事件与内部事件处理程序 MyEventHandler 。但这不是很优雅。我会喜欢能够写这个代替:

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

foo.Observer(Dim.LengthChanged);

但我不知道如何实现。也许我错过了一些很明显的东西?我想有些动态魔术可以做的伎俩,不知何故,但这不会强制编译时类型检查:我不想让用户 Observer 传递对不满足 System.EventHandler 事件签名的事件的引用。

解决方案

不幸的是,没有真正的方法这样做。



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

这些是无效扩展 - 如果有一个更干净的方式做,我相信他们会使用:(


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;
}

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:

  1. Define an interface ILengthChanged with the LengthChanged event, then make sure Dimension implements ILengthChanged. Then I have to provide one implementation of the Observer 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 a System.EventHandler event.

  2. 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 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)
    {
        ...
    }
    

    }

which would then be invoked like this:

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

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

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);

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.

解决方案

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.)

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆