2009-02-21 43 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(); 
}