是否有一种方法可以完成传递一个“事件”的等效功能?通过引用传递
本文关键字:事件 引用 功能 一个 方法 一种 是否 | 更新日期: 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);
};
无论如何,这是一个有趣的方式来了解更多关于事件和委托是如何工作的(或他们为什么不工作)。