2009-02-21 38 views
22

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

如果这是不可能的,我会使用add访问器将代表添加到列表中。这是最好的解决方案吗?

回答

20

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; 
3

更新(感谢评论者):代表不可替代意味着克隆对任务完成任何事情都没有成果。

当一个人写道:

myDelegate += AHandler 

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

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


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

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

为了证明这一点:

 
    class Program { 
     public delegate void MyDelegate(string name); 

     public event MyDelegate EventOne; 

     public void HandlerOne(string name) { 
      Console.WriteLine("This is handler one: {0}", name); 
     } 
     public void HandlerTwo(string name) { 
      Console.WriteLine("This is handler two: {0}", name); 
     } 
     public void HandlerThree(string name) { 
      Console.WriteLine("This is handler three: {0}", name); 
     } 

     public void Run() { 
      EventOne += HandlerOne; 
      EventOne += HandlerTwo; 
      Console.WriteLine("Before clone"); 
      EventOne("EventOne"); 

      
            
 
  
             MyDelegate eventTwo = (MyDelegate)EventOne.Clone();
            
  
      MyDelegate eventTwo = EventOne; 
      Console.WriteLine("After 
            
 
  
             clone
            
 copy"); 
      EventOne("EventOne"); 
      eventTwo("eventTwo"); 

      Console.WriteLine("Change event one to show it is different"); 
      EventOne += HandlerThree; 
      EventOne("EventOne"); 
      eventTwo("eventTwo"); 
     } 

     static void Main(string[] args) { 
      (new Program()).Run(); 
     } 
    } 
+0

克隆本身相对不重要 - 委托是不可变的,所以您可以复制委托引用。 – 2009-02-21 08:57:10

+0

除非在样本中,您想要独立修改原件或复印件。 – Richard 2009-02-21 09:09:19

13

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

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

看看my article on events,看看能否帮到你。如果没有,请给出关于你想要做什么的更多细节,指定你可以修改哪些代码,哪些不是。

1

如果你需要检查外部类的订户'事件:

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