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

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(使用前将#替换为@)

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

  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 按成员序列化

    我已经实现了template
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • 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 我怎样才能做到这一点 我正在使用最小起订量 如果这很重要的话 我认为没有办法从类外部检查事件处理程序委托 如果我错