我如何获得活动的订阅者?

我需要将一个事件的订阅者复制到另一个事件。 我可以获得一个事件的订阅者(比如MyEvent [0]返回一个委托)吗?

如果这不可能,我会使用add accessor将委托添加到列表中。 那会是最好的解决方案吗?

C#事件/委托是多播的,因此委托本身就是一个列表。 在课堂上,为了获得个人来电,您可以使用:

if(field != null) { // or the event-name for field-like events // or your own event-type in place of EventHandler foreach(EventHandler subscriber in field.GetInvocationList()) { // etc } } 

但是,要一次性分配所有内容,只需使用+ =或直接赋值:

 SomeType other = ... other.SomeEvent += localEvent; 

如果事件是由另一个类发布的事件,则不能 – 至少不可靠。 虽然我们经常认为事件只是一个委托变量,但它实际上只是一对方法:添加和删除(或订阅和取消订阅)。

如果它是您自己发布事件的代码,则很容易 – 您可以使添加/删除访问器执行您喜欢的任何操作。

看看我关于事件的文章 ,看看这对你有帮助。 如果没有,请提供有关您要执行的操作的更多详细信息,指定您可以修改哪些代码以及哪些代码无法修改。

更新(感谢评论者):委托不可用性意味着克隆在任务中无法实现。

当一个人写道:

 myDelegate += AHandler 

创建一个全新的委托实例并将其分配给myDelegate。

因此,如果没有克隆调用,下面的代码将完全相同。


MulticastDelegate(基础类型)具有克隆方法。

为了能够访问底层委托,您可能需要避免使用event关键字生成的常用帮助程序,并直接管理事物(自定义添加和删除访问者)。

为了表明这一点:

    课程{
         public delegate void MyDelegate(string name);

        公共事件MyDelegate EventOne;

         public void HandlerOne(string name){
             Console.WriteLine(“这是处理程序一:{0}”,名称);
         }
         public void HandlerTwo(string name){
             Console.WriteLine(“这是处理程序二:{0}”,名称);
         }
         public void HandlerThree(string name){
             Console.WriteLine(“这是处理程序三:{0}”,名称);
         }

         public void Run(){
             EventOne + = HandlerOne;
             EventOne + = HandlerTwo;
             Console.WriteLine(“克隆之前”);
             EventOne( “EventOne”);

             MyDelegate eventTwo =(MyDelegate)EventOne.Clone();
             MyDelegate eventTwo = EventOne;
             Console.WriteLine(“ 克隆后复制”);
             EventOne( “EventOne”);
             eventTwo( “eventTwo”);

             Console.WriteLine(“更改事件一以显示它是不同的”);
             EventOne + = HandlerThree;
             EventOne( “EventOne”);
             eventTwo( “eventTwo”);
         }

         static void Main(string [] args){
             (新程序())。Run();
         }
     }

如果您需要检查外部类事件的订阅者:

 EventHandler e = typeof(ExternalClass) .GetField(nameof(ExternalClass.Event), BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(instanceOfExternalClass) as EventHandler; if (e != null) { Delegate[] subscribers = e.GetInvocationList(); }