我可能会稍微过度思考这一点,但我可以帮助找出一种方法/最佳方式来做到以下几点。
我有一个附加到对象的事件处理程序,该对象是另一个类的属性。在我的事件处理程序中,我需要有关导致事件的对象的其他元数据(即包含它的对象的ID)。从发件人和事件信息中无法获得我需要的信息。我倾向于这是一个使用捕获变量的好地方,但我不确定我的实现想法。
因此,为了在代码中说明,我有一个事件处理程序:
void MyEventHandler(object sender, EventArgs e){
//Do Stuff here
}
(作为一个注释,我在这里使用了基本的EventArgs,但在我的实际实现中,它是一个专门的子类,并且使用通用的EventHandler声明了事件)
我目前正在附上它:
topObject.SubObject.EventToHandle += MyEventHandler;
我稍后会这样解读它:
topObject.SubObject.EventToHandle -= MyEventHandler;
我在处理事件时想要topObject的ID,所以我要更改MyEventHandler以获得以下签名:
void MyEventHandler(int id, object sender, EventArgs e)
并附加事件处理程序,如下所示:
topObject.SubObject.EventToHandle += (s,e) => MyEventHandler(topObject.ID, s,e);
我对此的担忧有两方面。
由于这两个问题,我的想法是创建一个Action并保存动作并使用它直到我需要删除事件处理程序。我做了以下事情:
Action<object, EventArgs> handler = (s,e) => MyEventHandler(topObject.ID, s,e);
topObject.SubObject.EventToHandle += handler;
我知道该动作无法转换为事件处理程序。是否有一些简单的方法可以进行此转换,仍然可以确保我可以分离事件处理程序?我只是在想这个/有没有一种方法我现在没有看到这样做?
答案 0 :(得分:1)
您可以创建包装现有事件处理程序的所有不错的包装函数,并为它们提供对象ID,但您仍然必须显式存储生成的委托以取消订阅事件。
我看到没有丑陋包装的唯一好办法就是使用反应式扩展。它本质上允许您将事件转换为IObservable,然后您可以将任何运算符应用于生成的IObservable(例如,Select将根据您的情况执行此操作)。但它仍然不那么优雅。
答案 1 :(得分:0)
引发事件的类中的事件处理程序签名应为:
protected void OnMyEvent(object sender, EventArgs e)
{
....
}
或
protected void OnMyEvent(object sender, MyEventArgs e)
{
....
}
在这种情况下,调用者会执行以下代码:
topObject.SubObject.MyEvent -= OnSubObjectMyEvent;
并像这样实现OnSubObjectMyEvent(示例):
private void OnSubObjectMyEvent(object sender, MyEventArgs e)
{
int topObjectId = ((SubObjectType)sender).TopObject.Id;
...
}
这里我假设SubObject有一个TopObject属性,允许我获取顶级对象的id。
这就是大多数.NET Framework类的工作方式。这种方法有什么问题吗?
答案 2 :(得分:0)
如果事件处理程序需要top对象的Id,我猜它不会破坏你设计中的一些抽象层,让他们意识到彼此。
换句话说,您的事件处理程序可能如下所示:
void Handler(object sender, EventArgs e)
{
var s = (SubObject) sender;
int id = s.TopObject.ID;
// do something with id...
}
我会将事件签名保留在sender和args的约定中。
答案 3 :(得分:0)
请勿更改活动的签名。虽然CLR在技术上允许事件的任何签名,但有理由为整个框架设计具有签名(object sender, EventArgs args)
的事件。实际上,对于违反此签名的事件CA1009: Declare event handlers correctly:
事件处理程序方法需要两个 参数。第一种是类型 System.Object并命名为'sender'。 这是提出的对象 事件。第二个参数是类型 System.EventArgs并命名为'e'。
有几种解决方案(替代方案):