Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为事件的添加访问器编写单元测试_C#_Unit Testing_Events - Fatal编程技术网

C# 为事件的添加访问器编写单元测试

C# 为事件的添加访问器编写单元测试,c#,unit-testing,events,C#,Unit Testing,Events,我有一个从第三方程序集调用的方法,作为我们的应用程序入口点。此方法引发我们的事件MyEvent。为了确保同一事件处理程序只注册一次,而且只注册一次,我实现了自己的逻辑,用于add和remove: class MyEditorExtension { private EventHandler<MyArgs> myEvent public EventHandler<MyArgs> MyEvent { add {

我有一个从第三方程序集调用的方法,作为我们的应用程序入口点。此方法引发我们的事件
MyEvent
。为了确保同一事件处理程序只注册一次,而且只注册一次,我实现了自己的逻辑,用于
add
remove

class MyEditorExtension
{
    private EventHandler<MyArgs> myEvent
    public EventHandler<MyArgs> MyEvent
    {
        add
        {
            if(this.myEvent == null || this.myEvent.GetInvocationList().All(x => !x.Equals(value))
                this.myEvent += value;
        }
        remove { this.myEvent -= value; }
    }

    // this method is called from ArcMap
    public void OnCreate()
    {
        ...
        MyEvent();
    }
}
当然,上面的内容不会编译,因为我不能在类之外引发事件。我还想避免仅仅为了测试事件而引入
RaiseEvent
-方法


因此,我想知道是否有任何方法可以实现这一点,例如使用反射?

事实上,使用反射是可能的。然而,这是相当黑客。事实上,在测试遗留代码时,这是一个常见的问题。此解决方案的灵感来自以下帖子:

您必须知道,事件只不过是围绕私有(隐藏)委托字段的
add
-和
remove
-方法,就像属性只不过是围绕私有(也隐藏)备份字段的get-and-set方法一样。说到这里,您可以访问该委托,该委托通常与您的事件具有完全相同的名称:

var delegateField = typeof(MyExtension).GetField("MyEvent", BindingFlags.NonPublic)?.GetValue(target);
在我们的特殊情况下,我们有自己的访问器,因此代理的名称直接在
MyExtension
的源cde中提供。因此,我们写了一个稍微不同的版本:

var delegateField = typeof(MyExtension).GetField("myEvent", BindingFlags.NonPublic)?.GetValue(target);
现在我们有了支持委托,我们可以很容易地调用它:

delegateField?.DynamicInvoke(new MyArgs());
当然,我们应该添加一些健全性检查,例如,对于代理被重命名,因此无法找到的情况,但我想你明白了

delegateField?.DynamicInvoke(new MyArgs());