Como obtenho os assinantes de um evento?

Eu preciso copiar os assinantes de um evento para outro evento. Posso obter os assinantes de um evento (como MyEvent [0] retornando um delegado)?

Se isso não for possível, usaria o acessador add para adicionar os delegates a uma lista. Essa seria a melhor solução?

C # events / delegates são multicast, portanto, o delegado é em si uma lista. De dentro da class, para obter chamadas individuais, você pode usar:

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 } } 

No entanto, para atribuir tudo de uma vez, basta usar + = ou atribuição direta:

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

Se o evento é um publicado por outra class, você não pode – pelo menos, não de forma confiável. Embora muitas vezes pensemos em um evento como sendo apenas uma variável delegada, na verdade é apenas um par de methods: adicionar e remover (ou inscrever-se e cancelar a inscrição).

Se é o seu próprio código que está publicando o evento, é fácil – você pode fazer com que os acessadores de adicionar / remover façam o que quiserem.

Dê uma olhada no meu artigo sobre events e veja se isso ajuda você. Se não, por favor, dê mais detalhes sobre o que você quer fazer, especificando quais pedaços de código você pode modificar e quais não são.

Atualizar (agradecer aos comentadores): a imunidade do delegado significa que a clonagem não alcança nada sobre uma tarefa.

Quando se escreve:

 myDelegate += AHandler 

uma instância de delegado completamente nova é criada e atribuída a myDelegate.

Portanto, o código abaixo funcionaria exatamente da mesma maneira sem a chamada de clonagem.


MulticastDelegate (o tipo subjacente) tem um método Clone.

Para poder obter o delegado subjacente, pode ser necessário evitar o auxiliar usual que a palavra-chave do evento gera e gerenciar as coisas diretamente (customizar e remover os acessadores).

Para mostrar isso:

     Programa de aula {
         delegado público void MyDelegate (nome da string);

         evento público MyDelegate EventOne;

         public void HandlerOne (nome da string) {
             Console.WriteLine ("Este é um manipulador: {0}", nome);
         }
         public void HandlerTwo (nome da string) {
             Console.WriteLine ("Este é o manipulador dois: {0}", nome);
         }
         public void HandlerThree (nome da string) {
             Console.WriteLine ("Este é o manipulador três: {0}", nome);
         }

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

             MyDelegate eventTwo = (MyDelegate) EventOne.Clone ();
             MyDelegate eventTwo = EventOne;
             Console.WriteLine ("Depois da cópia clone ");
             EventOne ("EventOne");
             eventTwo ("eventTwo");

             Console.WriteLine ("Alterar o evento um para mostrar que é diferente");
             EventOne + = HandlerThree;
             EventOne ("EventOne");
             eventTwo ("eventTwo");
         }

         static void Main (string [] args) {
             (novo Program ()). Run ();
         }
     }

Caso você precise examinar os assinantes de um evento de uma class externa:

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