是否有一种方法可以完成传递一个“事件”的等效功能?通过引用传递

本文关键字:事件 引用 功能 一个 方法 一种 是否 | 更新日期: 2023-09-27 18:06:02

我把"event"加了引号,因为我意识到它有点语法糖,而不是真正的类型。

我有一些事件被简单地链接到另一个类中的匹配事件。当事件被触发时,段落就像

提升者->代理->订阅者

在Proxy类中,我有一个像这样的通用模式:

Raiser.SomeEvent += 
    (_, args) =>
    {
        if (this.SomeEvent != null)
            this.SomeEvent(this, args);
    };

为了整理我的代码,我想把它移到另一个方法,返回一个新的委托,包装上面的事件调用代码:

public static EventHandler GetHandlerDelegate(EventHandler handler, Object sender)
{
    return
        (_, args) =>
        {                
            if (handler != null)
                handler(sender, args);
        };
    }      

在Proxy中输入:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this);

哪个更整洁。

只要订阅者不决定订阅代理,这就很好。SomeEvent 在上面的调用之后。不幸的是,我没有像我希望的那样通过引用传递"事件";我现在明白我只是传递调用列表,所以当OtherClass.SomeEvent发生时,调用匿名方法并调用它给定的"事件"(委托),只有在我调用GetHandlerDelegate()时已添加到该事件的委托将被调用。虽然这对我目前的情况来说已经足够了,但是这样编码是不可接受的。

我已经读了一些其他的SO问题,我收集有一个叫做响应式扩展的东西,可能会有所帮助,但在这个时候,我正在寻找一个更简单的解决方案,如果有一个。(如果没有,我就不做了。)

有没有别的方法可以让我完成我想做的事情,而没有上述缺点?


如果这个问题不清楚,请看看我的答案,希望能帮助澄清它。

是否有一种方法可以完成传递一个“事件”的等效功能?通过引用传递

编辑:好了,我想我现在明白了。其实很简单。你应该能够写代理只是有一个事件,然后使代理本身订阅的事件,像这样(只是EventHandler -我将在后面来):

Proxy proxy = new Proxy();
raiser.SomeEvent += Proxy.Handler;
// Then in the subscriber...
proxy.ProxiedEvent += (whatever)
// And the proxy class...
public class Proxy
{
    public event EventHandler ProxiedEvent;
    public void Handler(object sender, EventArgs e)
    {
        EventHandler proxied = ProxiedEvent;
        if (proxied != null)
        {
            // Or pass on the original sender if you want to
            proxied(this, e);
        }
    }
}

现在,这里的困难是让它一般地工作。我现在想不出任何办法,虽然我现在有点分心。

这是你想的那种事情吗,或者它至少能帮助你以不同的方式思考问题吗?

既然我最初的目标是:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this); 

是不可能的,我妥协了,想出了这个:

Raiser.SomeEvent += (_, args) => RaiseEvent(this.SomeEvent, this, args); 

GetHandlerDelegate()将返回一个引发事件的委托,RaiseEvent()只是(你猜对了)引发事件。

public static void RaiseEvent(EventHandler _event, Object sender, EventArgs args)
{
    if (_event != null)
        _event(sender, args);
}

并使用自定义EventArgs来支持事件:

public static void RaiseEvent<TArgs>(EventHandler<TArgs> _event, Object sender, TArgs args)
    where TArgs : EventArgs
{
    if (_event != null)
        _event(sender, args);
}

我把这些方法放在一个静态助手类中,所以实际的调用稍微难看一些;下面是一个例子:

ViewControl.OpenFilesetClick += (_, args) => EventHelper.Raise(OpenFilesetClick, this, args); 

(我还将方法重命名为Raise(),并从传递的事件名称中删除了可选的this)。

但我不完全相信这是否值得,考虑到另一种选择可能更容易阅读:

ViewControl.OpenFilesetClick += (_, args) => 
{
    if (OpenFilesetClick != null)
        OpenFilesetClick(this, args);
};

无论如何,这是一个有趣的方式来了解更多关于事件和委托是如何工作的(或他们为什么不工作)。