我把“event”放在引号中,因为我意识到它是一些语法糖,而不是真正的类型。
我有一些事件只是链接到另一个类中的匹配事件。所以当事件发生时,这段话就像
Raiser - >代理 - >订户
所以在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);
};
}
然后在代理我可以做:
Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this);
哪个更整洁。
只要订阅者在上述调用之后没有决定订阅Proxy.SomeEvent ,这就没问题了。不幸的是,我并没有像我希望的那样通过参考传递“事件”;我现在明白我只是传递了调用列表,所以当OtherClass.SomeEvent
发生并调用匿名方法并调用“event”(委托)时,它被赋予了,只有已添加到该事件的代理我将调用调用GetHandlerDelegate()。虽然这实际上足以满足我目前的情况,但以这种方式进行编码实际上是不可接受的。
我已经阅读了其他一些SO问题,我收集了一些可能有帮助的Reactive Extensions,但此时我正在寻找一个更简单的解决方案(如果有的话)。 (如果没有,我就不会这样做。)
还有另一种方法可以完成我正在尝试做的事情,没有这个缺点吗?
如果这个问题不明确,请参阅my answer,希望有助于澄清它。
答案 0 :(得分:3)
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);
}
}
}
现在,困难在于让它一般地运作起来。我现在无法想到这样做的任何方式,虽然我现在有点分心。
这是你想到的事情,还是至少可以帮助你以不同的方式思考问题?
答案 1 :(得分:0)
由于我最初的目标:
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);
};
无论如何,这是一个有趣的方式来了解更多关于事件和代表如何工作(或他们如何工作)。