2009-02-21 9 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; 
+0

それを指摘してくれてありがとう。それは自分のコード内のイベントに最適です。 – weiqure

+0

ありがとうございます。私は、サブスクリプションされたイベントを楽しんでいないバイナリシリアライゼーションによるオブジェクトクローニングのための良い回避策が必要でした。そうでなければ、ICloneableを数百のクラスに実装しなければなりませんでした。 – user1039513

3

更新(投稿者に感謝します):代表者の免疫力とは、クローニングが割り当てに関して何も達成しないことを意味します。

myDelegate += AHandler 

完全に新しいデリゲートインスタンスが作成され、myDelegateに割り当てられます。1の書き込み

したがって、以下のコードはCloneコールなしでまったく同じように動作します。


MulticastDelegate(基本型)には、Cloneメソッドがあります。

基本的なデリゲートにアクセスできるようにするには、イベントキーワードによって生成される通常のヘルパーを避け、直接管理する必要があります(カスタムアクセサの追加と削除)。少なくとも、ない確実 -

 
    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

クローン自体は比較的重要ではありません - 代表団は不変ですので、あなただけのデリゲートの参照をコピーすることができます。 –

+0

サンプルの場合のように、オリジナルまたはコピーを個別に変更しない限り、 – Richard

+0

リチャード - いいえ、Clone()ステップなしで**同じように動作します**。 –

13

イベントが別のクラスによって公開1である場合は、することはできません。これを示すため

。イベントをデリゲート変数と考えることがよくありますが、実際にはイベントの追加と削除(または購読と購読解除)のペアです。

イベントを公開する独自のコードの場合は、簡単です。追加/削除のアクセサーに好きなようにすることができます。

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(); 
} 
関連する問題