如何将自己从事件处理程序中删除?

2023-11-26

我想做的基本上是从事件中删除函数,而不知道函数的名称。

我有一个FileSystemWatcher。如果创建/重命名文件,它会检查其名称。如果匹配,则会将其移动到特定位置。但是,如果文件被锁定,它会生成一个附加到计时器的滴答事件的 lambda,等待文件未被锁定。如果不是,它会移动文件,然后将自身从事件处理程序中删除。我见过很多方法可以做到这一点,例如保留实例或创建命名方法。我在这里都做不到。我有什么选择?


没有简单的方法可以实现这一点。

首选方法:

我不明白为什么你不能拯救代表。您不必将实例保存为某个字段。它可以是由匿名事件处理程序捕获的局部变量:

EventHandler<TypeOfEventArgs> handler = null;
handler = (s, e) =>
{
    // Do whatever you need to do here

    // Remove event:
    foo.Event -= handler;
}

foo.Event += handler;

我想不出有什么场景是不能使用它的。

不保存委托的替代方法:

然而,如果你遇到这样的情况,事情就会变得非常棘手。
您需要找到已作为事件处理程序添加的委托。因为你没有保存它,所以很难获得它。没有this获取当前正在执行的方法的委托。

你不能使用GetInvocationList()也可以在事件上,因为访问定义它的类之外的事件仅限于添加和删除处理程序,即+= and -=.

创建新的委托也是不可能的。虽然您可以访问MethodInfo定义匿名方法的对象,您无法访问声明该方法的类的实例。此类由编译器自动生成并调用this匿名方法内部将返回定义普通方法的类的实例。

我发现有效的唯一方法是找到事件使用的字段(如果有)并调用GetInvocationList()在上面。以下代码使用虚拟类演示了这一点:

void Main()
{
    var foo = new Foo();
    foo.Bar += (s, e) => {
        Console.WriteLine("Executed");
        
        var self = new StackFrame().GetMethod();
        var eventField = foo.GetType()
                            .GetField("Bar", BindingFlags.NonPublic | 
                                             BindingFlags.Instance);
        if(eventField == null)
            return;
        var eventValue = eventField.GetValue(foo) as EventHandler;
        if(eventValue == null)
            return;
        var eventHandler = eventValue.GetInvocationList()
                                     .OfType<EventHandler>()
                                     .FirstOrDefault(x => x.Method == self)
                               as EventHandler;
        if(eventHandler != null)
            foo.Bar -= eventHandler;
    };
    
    foo.RaiseBar();
    foo.RaiseBar();
}

public class Foo
{
    public event EventHandler Bar;
    public void RaiseBar()
    { 
        var handler = Bar;
        if(handler != null)
            handler(this, EventArgs.Empty);
    }
}

请注意该字符串"Bar"被传递到GetField需要是确切的名称field事件使用的。这会导致两个问题:

  1. 该字段可以以不同的方式命名,例如当使用显式事件实现时。您需要手动找出字段名称。
  2. 可能根本没有字段。如果事件使用显式事件实现并且仅委托给另一个事件或以其他方式存储委托,则会发生这种情况。

结论:

替代方法依赖于实现细节,因此如果可以避免,请不要使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将自己从事件处理程序中删除? 的相关文章

  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • 如何在 web.config 文件中更改我的 asp.net 网站的默认时区

    我正在尝试更改我的 asp net 网站的默认时区 我尝试了以下代码 但它不起作用
  • 如何为 List 实现 Parcelable

    我正在尝试在我的可打包中传递一个列表 public class MetaDados implements Parcelable private List
  • 哈希表与 C++ 中的 STL 映射

    我正在尝试学习 C 地图 只是想知道STL图的实现 我读到它采用了二叉搜索树 STL中有哈希表的实现吗 STL映射到底是如何存储键值对的 典型的 STL 实现基于红黑树 C TR1 提供了 std tr1 unordered map 它使用
  • 如何在 JMeter 中进行 OAuth 2.0 身份验证?

    我正在尝试对一些需要身份验证的 API OAuth 2 0 进行功能测试 并在 JMeter 中进行模拟 我正在尝试验证 Azure 云的 OAuth 服务 有没有人能够成功创建 JMeter HTTP 请求来针对 OAuth 2 0 进行
  • 在文本选择上显示自定义菜单

    您好 我希望能够在用户选择一些与媒体提供的文本非常相似的文本时显示自定义菜单 或上下文菜单 如何实现这样的事情 我知道本机 jquery 上下文菜单插件 但我如何知道用户何时选择文本 浏览器的onselect似乎仅在输入元素上受支持 这是一
  • PHP 的合并函数?

    许多编程语言都有合并函数 返回第一个非 NULL 值 example 遗憾的是 2009 年 PHP 还没有做到这一点 在 PHP 本身获得合并函数之前 在 PHP 中实现一个合并函数的好方法是什么 php 5 3 中有一个新的运算符可以执
  • 如何在 cmd start 中使用引号?

    这是我想做的事 start wait c Program Files NetDrive2 nd2cmd exe c m t ftp blabla If I do start wait c Program Files NetDrive2 nd
  • 如何在 Anaconda Env 中启动 Visual Studio Code

    我在 Windows 10 PC 上的 Visual Studio Code 中运行 Python 程序时遇到问题 当我从终端启动 python 会话并说import cv2我没有收到任何错误 当我通过命令提示符并启动时VSCode从环境中
  • 为什么 UI 元素必须始终从 UI 线程创建/更新?

    为什么 UI 元素必须始终从 UI 线程创建 更新 在 几乎 所有编程语言中 UI 元素只能从 UI 线程安全地访问 修改 我知道这是一个标准的并发访问和同步问题 但真的有必要吗 这种行为是由编程语言还是操作系统强加的 有没有什么编程语言可
  • Django - 仅包含日期部分的分组

    MyModel objects filter created at gte 2011 03 09 created at lte 2011 03 11 values created at status annotate status coun
  • 作为 Cowboy 客户端,您如何使用 Gun?

    我跟着入门说明对于 Cowboy 我让 Cowboy 在端口 8080 上运行并侦听 然后我得到了Hello Erlang 当我进入时的回应http localhost 8080在我的浏览器中 现在 如何使用 Gun 连接到 Cowboy
  • 在类中,“using Base::BaseOfBase;”应该做什么?

    考虑这段代码 include
  • GWT 中的配置参数存储在哪里?

    我可以在客户端哪里存储配置参数 我无法在 Servlet init 参数 web xml 中存储参数 因为我必须使用 PHP 那么我如何在客户端存储初始化应用程序参数 例如 PHP 脚本位置 一些密码等 为此 您有以下选择 将数据存储在客户
  • 对数组进行排序并反映另一个数组中的变化

    我有一个双精度数组 用 Java 编写 arr1我想要排序 最有可能的第一个选项是实用方法Arrays sort double 我的想法是我想要相同的更改 例如 值index i与值互换index j in arr1 反映在另一个整数数组中
  • 如何更改 Flutter 中 EditText 上气泡(光标下)的颜色

    如何更改在 Text 或 TextFormField 或 Flutter 中选择文本时出现的气泡的颜色 Here是同样的问题 但是对于本机代码 根据这个颤振文档 textSelectionHandleColor已弃用 你应该使用select
  • Scala 对现有变量的多重赋值

    我可以做类似的事情 def f Tuple2 String Long val a b f 如果变量已经存在怎么办 我在过滤器上运行相同的数据集 但我不想链接它们 长名称等 这是我尝试过的 但它抱怨期待 而不是最后一行的 var a init
  • 为什么原型函数不影响console.log?

    我制作了原型Function这样它就有一个 getBody 函数 Function prototype getBody function Get content between first and last var m this toStr
  • 列表视图有多个分割按钮吗?

    基于 JQuery Mobile 的示例拆分按钮列表我正在尝试在 Android 中生成一个列表视图组件 右侧有两个额外的按钮 一个紧挨着另一个 问题在于该代码仅生成一个按钮 第二个按钮作为当前项目的链接添加 这是我的代码 ul li a
  • 什么是控制字符的正则表达式?

    我试图匹配 c 形式的控制字符 其中 c 是控制字符的任何有效字符 我有这个正则表达式 但它当前不起作用 z 我认为问题在于插入符 是正则表达式解析引擎的一部分 匹配以下形式的 ASCII 文本字符串 X使用模式 仅此而已 匹配以下形式的
  • 如何将自己从事件处理程序中删除?

    我想做的基本上是从事件中删除函数 而不知道函数的名称 我有一个FileSystemWatcher 如果创建 重命名文件 它会检查其名称 如果匹配 则会将其移动到特定位置 但是 如果文件被锁定 它会生成一个附加到计时器的滴答事件的 lambd