c# - 订阅/取消订阅列表中的事件
问题描述
我有一个对象列表,我想为每个对象订阅/取消订阅一个事件(通过委托,因为我需要将额外的参数传递给方法)。所以我有这样的事情:
public void MonitoringCtrl(bool monitoringOn)
{
foreach (var mh in monHandlers)
{
evHandler = (sender, e) => OnNotification(sender, e, mh);
if (monitoringOn)
{
//subscribe to event
mh.monitoredItem.Notification += evHandler;
}
else
{
//unsubscribe
mh.monitoredItem.Notification -= evHandler;
}
}
//do other stuff
}
这在订阅时有效,但在取消订阅时不起作用,大概是因为我在 foreach 中重新声明了 evHandler。如何保存对 evHandler 的引用?
解决方案
这是因为在第二次调用时MonitoringCtrl()
(当您传递false
取消订阅时),会创建一个新的事件处理程序。但是该新实例不会取消订阅之前附加的事件处理程序实例。
您不需要为循环中的每个元素创建新的事件处理程序,也不得创建新的事件处理程序来取消订阅。您可以为所有事件保留一个事件处理程序作为成员变量。但是通过绑定到这样的方法更容易做到这一点:
public void MonitoringCtrl(bool monitoringOn)
{
foreach (var mh in monHandlers)
{
if (monitoringOn)
{
//subscribe to event
mh.monitoredItem.Notification += HandleNotification;
}
else
{
//unsubscribe
mh.monitoredItem.Notification -= HandleNotification;
}
}
//do other stuff
}
private void HandleNotification(object sender, EventArgs args)
{
//do event stuff
}
更新我刚刚看到您需要使用委托来获取其他参数
您可以使用本地函数来捕获父方法的属性,但在您的情况下,您需要捕获循环变量。那是行不通的,所以我会尝试找到一种方法来摆脱mh
困境,sender
因为它似乎是相关的。你想用 lambda ( )传递the和它sender
的monitoredItem
父级吗?monitorHandler
mh
推荐阅读
- algorithm - 这个算法问题的研究领域是什么?
- javascript - 如何从堆中删除未安装的组件?
- permalinks - 如何使用带有普通永久链接的 Woocommerce REST API?
- asp.net-mvc - IdentityServer4 用户管理与单独的 MVC 客户端 (AspNetIdentity)
- flutter - 流未在另一个流侦听功能中更新
- c# - '在 Visual Studio 2019 中找不到本地数据库选项'
- spring - 将对象列表分页到 Angular 7
- jsonschema - api-blueprint 没有正确显示嵌套的“一个”属性
- string - 将字符串表达式转换为实际工作实例表达式
- javascript - 如何使 svg 元素围绕 svg 路径移动?