如何测试事件是否包含事件处理程序?

2024-03-26

我想测试那个班级A's RegisterEventHandlers()方法将其方法之一注册为EventHandler课堂活动B。我怎样才能做到这一点?我正在使用最小起订量,如果这很重要的话。

  • 我认为没有办法从类外部检查事件处理程序委托(如果我错了,请纠正我)。
  • 如果我可以触发事件然后断言我的回调被调用,那就太好了,但是如果我模拟A类(并设置回调的期望)然后我失去了实现RegisterEventHandlers(),这是我首先要测试的方法。
  • 嘲笑B类的事件将是最好的选择,但我不知道我必须拦截什么方法才能做到这一点。有没有办法为事件设置模拟并拦截+=方法调用?

有一个干净的解决方案吗?


您可以在声明事件的类之外获取事件的调用列表 - 但它涉及反射。下面是一个代码示例,显示如何确定哪些方法(在目标实例上)a) 添加到事件中b.事件致电后a.RegisterEventHandlers()。将以下代码粘贴到代码文件中并添加到表单或控制台项目:测试测试 = new Test();测试运行();

using System;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;

   public class A
   {
      B m_b = new B();

      public void RegisterEventHandlers()
      {
         m_b.TheEvent += new EventHandler(Handler_TheEvent);
         m_b.TheEvent += new EventHandler(AnotherHandler_TheEvent);
      }

      public A()
      { 
         m_b.TheEvent += new EventHandler(InitialHandler_TheEvent);
      }

      void InitialHandler_TheEvent(object sender, EventArgs e)
      { }

      void Handler_TheEvent(object sender, EventArgs e)
      { }

      void AnotherHandler_TheEvent(object sender, EventArgs e)
      { }
   }

   public class B
   {
      public event EventHandler TheEvent;
      //{
      //   //Note that if we declared TheEvent without the add/remove methods, the
      //   //following would still generated internally and the underlying member
      //   //(here m_theEvent) can be accessed via Reflection. The automatically
      //   //generated version has a private field with the same name as the event
      //   //(i.e. "TheEvent")

      //   add { m_theEvent += value; }
      //   remove { m_theEvent -= value; }
      //}
      //EventHandler m_theEvent; //"TheEvent" if we don't implement add/remove


      //The following shows how the event can be invoked using the underlying multicast delegate.
      //We use this knowledge when invoking via reflection (of course, normally we just write
      //if (TheEvent != null) TheEvent(this, EventArgs.Empty)
      public void ExampleInvokeTheEvent()
      {
         Delegate[] dels = TheEvent.GetInvocationList();
         foreach (Delegate del in dels)
         {
            MethodInfo method = del.Method;
            //This does the same as ThisEvent(this, EventArgs.Empty) for a single registered target
            method.Invoke(this, new object[] { EventArgs.Empty });
         }
      }
   }


   public class Test
   {
      List<Delegate> FindRegisteredDelegates(A instanceRegisteringEvents, B instanceWithEventHandler, string sEventName)
      {
         A a = instanceRegisteringEvents;
         B b = instanceWithEventHandler;

         //Lets assume that we know that we are looking for a private instance field with name sEventName ("TheEvent"), 
         //i.e the event handler does not implement add/remove.
         //(otherwise we would need more reflection to determine what we are looking for)
         BindingFlags filter = BindingFlags.Instance | BindingFlags.NonPublic;

         //Lets assume that TheEvent does not implement the add and remove methods, in which case
         //the name of the relevant field is just the same as the event itself
         string sName = sEventName; //("TheEvent")

         FieldInfo fieldTheEvent = b.GetType().GetField(sName, filter);

         //The field that we get has type EventHandler and can be invoked as in ExampleInvokeTheEvent
         EventHandler eh = (EventHandler)fieldTheEvent.GetValue(b);

         //If the event handler is null then nobody has registered with it yet (just return an empty list)
         if (eh == null) return new List<Delegate>();


         List<Delegate> dels = new List<Delegate>(eh.GetInvocationList());

         //Only return those elements in the invokation list whose target is a.
         return dels.FindAll(delegate(Delegate del) { return Object.ReferenceEquals(del.Target, a); });
      }

      public void Run()
      {
         A a = new A();

         //We would need to check the set of delegates returned before we call this

         //Lets assume we know how to find the all instances of B that A has registered with
         //For know, lets assume there is just one in the field m_b of A.
         FieldInfo fieldB = a.GetType().GetField("m_b", BindingFlags.Instance | BindingFlags.NonPublic);
         B b = (B)fieldB.GetValue(a);

         //Now we can find out how many times a.RegisterEventHandlers is registered with b
         List<Delegate> delsBefore = FindRegisteredDelegates(a, b, "TheEvent");

         a.RegisterEventHandlers();

         List<Delegate> delsAfter = FindRegisteredDelegates(a, b, "TheEvent");

         List<Delegate> delsAdded = new List<Delegate>();
         foreach (Delegate delAfter in delsAfter)
         {
            bool inBefore = false;
            foreach (Delegate delBefore in delsBefore)
            {
               if ((delBefore.Method == delAfter.Method)
                  && (Object.ReferenceEquals(delBefore.Target, delAfter.Target)))
               {
                  //NOTE: The check for Object.ReferenceEquals(delBefore.Target, delAfter.Target) above is not necessary 
                  //     here since we defined FindRegisteredDelegates to only return those for which .Taget == a)

                  inBefore = true;
                  break;
               }
            }
            if (!inBefore) delsAdded.Add(delAfter);
         }

         Debug.WriteLine("Handlers added to b.TheEvent in a.RegisterEventHandlers:");
         foreach (Delegate del in delsAdded)
         {
            Debug.WriteLine(del.Method.Name);
         }


      }
   }




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

如何测试事件是否包含事件处理程序? 的相关文章

  • 通过 SocketCAN 进行 boost::asio

    我正在考虑利用升压阿西奥 http www boost org doc libs 1 49 0 doc html boost asio html从a读取数据套接字CAN http en wikipedia org wiki SocketCA
  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 如何保证对象只有一个线程

    我有以下代码 class Service public void start creates thread which creates window and goes to message loop void stop sends WM C
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • 如何在 C# 控制台应用程序中将修饰符(ctrl、alt、shift)按键捕获为单个按键?

    Console ReadKey 仅在按下 正常 键时捕获输入 然后将修饰符 如果有 附加为键信息的一部分 如何将单个修饰键注册为输入 提供了一种解决方案这个链接 https blogs msdn microsoft com toub 200
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 从 WebBrowser 控件 C# 获取滚动值

    我试图在 WebBrowser 控件中获取网页的 Y 滚动索引 但无法访问内置滚动条的值 有任何想法吗 对于标准模式下的 IE 使用文档类型 正如你所说 scrollTop是的财产元素 而不是 HtmlDocument htmlDoc th
  • Visual Studio Code:如何配置 includePath 以获得更好的 IntelliSense 结果

    我是使用 Visual Studio Code 的完全初学者 我不知道我在做什么 我已经四处搜索 也许还不够 但我找不到像我这样的人如何配置的简单解释c cpp properties json每当我单击带有绿色波浪线下划线的行旁边的黄色灯泡
  • std::forward_as_tuple 将参数传递给 2 个构造函数

    我想传递多个参数以便在函数内构造两个对象 以同样的方式std pair
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 如何通过 JsonConvert.DeserializeObject 在动态 JSON 中使用 null 条件运算符

    我正在使用 Newtonsoft 反序列化已知的 JSON 对象并从中检索一些值 如果存在 关键在于对象结构可能会不断变化 因此我使用动态来遍历结构并检索值 由于对象结构不断变化 我使用 null 条件运算符来遍历 JSON 代码看起来像这
  • 每个租户的唯一用户名和电子邮件

    我正在使用以下代码编写多租户应用程序ASP NET Core 2 1 我想覆盖默认的与用户创建相关的验证机制 目前我无法创建多个具有相同的用户UserName My ApplicationUser模型有一个名为TenantID 我想要实现的
  • 如何分析组合的 python 和 c 代码

    我有一个由多个 python 脚本组成的应用程序 其中一些脚本正在调用 C 代码 该应用程序现在的运行速度比以前慢得多 因此我想对其进行分析以查看问题所在 是否有工具 软件包或只是一种分析此类应用程序的方法 有一个工具可以将 python
  • 如何在 Go 中将环境变量传递给测试用例

    在为 Go 编写测试用例时 传递需要提供给测试的环境变量的标准方法是什么 例如 我们不想在测试用例的源代码中嵌入密码 处理这个问题最标准的方法是什么 我们让测试用例寻找配置文件吗 还有别的事吗 看来我偶然发现了答案 将其添加到测试用例中可以
  • 我可以让 ungetc 取消阻止阻塞的 fgetc 调用吗?

    我想在收到 SIGUSR1 后使用 ungetc 将 A 字符重新填充到标准输入中 想象一下我有充分的理由这样做 调用 foo 时 stdin 中的阻塞读取不会被收到信号时的 ungetc 调用中断 虽然我没想到它会按原样工作 但我想知道是
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6

随机推荐

  • HTML5视频播放器:动态加载视频

    那么 使用兼容 HTML 5 的视频播放器 如 Video JS 如何动态加载视频 而无需重新加载整个页面呢 想象一下 一个链接列表 类似于播放列表 每个链接都指向一个视频 单击链接时 我想将所选视频加载到播放器中 目前 我正在使用一个包含
  • 在vim中打开目录

    我是一名 mac 用户 正在认真尝试 vim 我习惯的大多数 GUI 编辑器都允许我通过执行以下命令来将目录作为 项目 打开 编辑 www example com vim 等效项vim www example com 将显示目录中的文件列表
  • 如何将 STDERR 重定向到 STDOUT,但忽略原始 STDOUT? [复制]

    这个问题在这里已经有答案了 我有一个程序STDERR我想要检查并运行的输出grep on etc 所以我可以将其重定向到STDOUT并使用 grep 但问题是 我这样做not想要原件STDOUT内容 所以 这个不行 cmd 2 gt 1 g
  • 为什么选择静态类而不是单例实现?

    静态与静态 单例问题之前在 SO 中已经讨论过很多次了 然而 所有的答案都指出了单例的许多优点 我的问题是 静态类比单例有什么优点 为什么不每次都简单地选择一个单例呢 静态类是你盒子里的一个技术工具 基本上是一个语言功能 Singleton
  • SQL聚合函数选择唯一值

    我有一个包含两列的行集 technical id and natural id 行集实际上是复杂查询的结果 假设列值之间的映射是双射的 即对于具有相同值的两行 technical id the natural ids 也相同 对于不同的te
  • iPhone 应用程序可以阻止电话吗?

    是否可以编写一个应用程序来阻止传入和传出的电话 还是 iPhone 被锁定太多了 谢谢 编辑 请参阅下面 Rajan Maheshwari 的回答 CallKit 现在提供了这一点 即使那些看似永远不会改变的事情 最终也可能会改变 任何修改
  • Django 从 postgres JSON 字段获取值

    我有一个简单的模型 例如 class MyModel models Model data JSONField JSON 字段data结构如下 name Brian skills id 4 name First aid id 5 name S
  • 如何删除 Visual Studio PIN TAB 图标(显然在选项卡上)

    有没有办法完全删除 Visual Studio 2010 中的 pin 选项卡选项 如何 我一直不小心点击它 我希望它消失 我从不使用它并且总是不小心点击它 thnx 附注右键单击 PIN 图标确实会弹出一些自定义对话框 但无法删除它 无法
  • SimpleHTTPServer 添加 default.htm default.html 到索引文件

    我总是用 python m SimpleHTTPServer对于快速本地静态 Web 测试 它非常适合index htm or index html作为索引文件 不过我需要使用default htm or default html对于我目前
  • Sequelize cli 模型创建

    我一直在尝试创建一个user model使用sequelize cli 但每当我插入更多参数 如主键和唯一 时 解析器就会失败 例如 npx sequelize model create name user attributes name
  • 通过序言格式化 csv 表?

    尽我所能 我无法弄清楚如何更改 sphinx 的 pdf 输出中的默认表格格式 我可以编辑 tex 文件或 writer py 源代码 但这两个似乎都是不好的选择 有什么东西可以通过序言来实现这一点吗 取决于您试图通过更改表格格式来完成的任
  • OWL 中表达式前面的列表?

    OWL 中表达式前面是否可以有一个列表 就像是 Dairy Egg Nut rdfs subClassOf FoodGroup or Dairy Egg Nut rdfs subClassOf FoodGroup 或者一般来说 是否存在针对
  • PHP 日期时间字符串区分

    在这两种情况下 我都可以从字符串创建日期对象 如下所示 dt strtotime 2013 04 19 17 00 00 or dt strtotime 10 hours 我需要一种方法来区分这两种日期类型 无论是相对数据字符串还是绝对数据
  • Windows 7 上的全屏 OpenGL 窗口打开的模态对话框不显示

    看来我的问题可能与未回答的相关问题相同 Windows 7 上出现 GLUT 的 OpenGL 全屏模式不显示消息框 https stackoverflow com questions 1842312 opengl with glut on
  • Ajax 追加加载

    它必须是jquery 我有文件 text html 其中有 6 个 div a b c d e f 在另一个文件中 我有一个 div 我喜欢它将 a b c d e f 的内容填充到该单个 div 中 我尝试过 load 但 b 替换了 a
  • ImageMagick - “未找到 CORE_RL_magick_.dll”或如何使用 ruby​​ 1.9.2 在 Windows 上安装 RMagick

    我正在开发 Rail3 应用程序 经过几个小时的努力 终于在 win7x64 ruby 1 9 2 上安装了 rmagick 2 13 1 gem 没有错误 我遇到了另一个错误 是的 我听说 Windows 中的 Rails 体验可能会很痛
  • 按一天中的时间自动切换 Windows 10 中的暗/亮模式(无需修改或更改主题!)

    如今大多数设备都允许自动切换暗 亮模式 但 Windows 10 似乎没有这样的功能 有办法做到这一点吗 例如使用任务计划程序 似乎有很多关于如何以编程方式更改窗口 主题 的示例 但没有关于亮 暗模式切换的示例 可以在 设置 颜色 中为 W
  • jQuery 圆函数

    如何使用 jQuery 对数字进行四舍五入 如果数字是 3168 我想将其打印为 32 或者 如果数字为 5233 则结果应为 52 我怎样才能做到这一点 我应该使用Math round功能 是的 您应该使用 Math round 除以 1
  • 并发数据结构设计

    我正在尝试提出用于高吞吐量 C 服务器的最佳数据结构 该数据结构将用于存储从几到几百万个对象的任何内容 并且不需要排序 尽管可以非常便宜地提供唯一的排序键 要求是它能够支持高效的插入 最好是 O 1 中等效率的删除和高效的遍历 它不需要支持
  • 如何测试事件是否包含事件处理程序?

    我想测试那个班级A s RegisterEventHandlers 方法将其方法之一注册为EventHandler课堂活动B 我怎样才能做到这一点 我正在使用最小起订量 如果这很重要的话 我认为没有办法从类外部检查事件处理程序委托 如果我错