2010-06-09 12 views
12

Cuando se suscribe a un evento en .NET, la suscripción se agrega a un delegado de multidifusión. Cuando se dispara el evento, se llama a los delegados en el orden en que se suscribieron.¿Puedo revertir el orden de un evento delegado de multidifusión?

Me gustaría sobrescribir la suscripción de alguna manera, para que las suscripciones realmente se activen en el orden inverso inverso. ¿Se puede hacer esto, y cómo?

creo que algo como esto podría ser lo que necesito ?:

public event MyReversedEvent 
{ 
    add { /* magic! */ } 
    remove { /* magic! */ } 
} 
+2

, pensé que el orden en que se activaron las suscripciones era indeterminado. – ChrisF

+0

@ChrisF: de MSDN ... "Un MulticastDelegate tiene una lista de delegados vinculada, llamada lista de invocación, que consta de uno o más elementos. Cuando se invoca un delegado de multidifusión, los delegados en la lista de invocación se llaman de forma síncrona en el orden en el que aparecen ". –

+0

@Robert - Ah, claramente pasé por alto el bit ** multicast ** - tiempo para dejar de buscar preguntas para responder e irme a la cama. – ChrisF

Respuesta

5

Controlling When and If a Delegate Fires Within a Multicast Delegate

El siguiente método crea un delegado de multidifusión llamado allinstances y luego utiliza GetInvocationList para permitir que cada delegado a ser despedido de forma individual, en orden inverso:

public static void InvokeInReverse() 
{ 
    MyDelegate myDelegateInstance1 = new MyDelegate(TestInvoke.Method1); 
    MyDelegate myDelegateInstance2 = new MyDelegate(TestInvoke.Method2); 
    MyDelegate myDelegateInstance3 = new MyDelegate(TestInvoke.Method3); 

    MyDelegate allInstances = 
      myDelegateInstance1 + 
      myDelegateInstance2 + 
      myDelegateInstance3; 

    Console.WriteLine("Fire delegates in reverse"); 
    Delegate[] delegateList = allInstances.GetInvocationList(); 
    for (int counter = delegateList.Length - 1; counter >= 0; counter--) 
    { 
     ((MyDelegate)delegateList[counter])(); 
    } 
} 
+0

Gracias - Lo intenté justo antes de publicar su respuesta y funcionó - es bueno ver la confirmación de que he hecho lo correcto. :) –

5

Una opción sería la de manejar esto cuando se eleva el evento. Puede obtener los suscriptores del evento a través del Delegate.GetInvocationList, y simplemente llame a cada delegado en orden inverso usted mismo.

+0

Gracias. Lo intenté justo antes de publicar su respuesta y funcionó, es bueno ver la confirmación de que hice lo correcto. :) –

+0

@SLaks: Interesante. Gracias - no había usado los operadores de delegado de esa manera antes ... –

19

No es necesario cualquier magia; solo necesitas invertir la suma.
Escribir delegate1 + delegate2 devuelve un nuevo delegado que contiene el (los) método (s) en delegate1 seguido de los métodos en delegate2.

Por ejemplo:

private EventHandler myReversedEventField; 
public event EventHandler MyReversedEvent 
{ 
    add { myReversedEventField = value + myReversedEventField; } 
    remove { myReversedEventField -= value; } 
} 

que no es necesario ningún tipo de magia en el controlador remove, a menos que desee quitar la última aparición de ese controlador en lugar del primero. (En caso de que se haya agregado el mismo controlador dos veces)

+0

¿Puedes ampliar un poco tu respuesta, por favor? Sería bueno ver el contexto alrededor del código que publicaste, para poder ver dónde debería ubicarlo. –

+0

gracias por la actualización de su respuesta. –

+0

@Neil, Parte de información de contexto aquí: http://www.gavaghan.org/blog/2007/07/25/intercepting-add-and-remove-of-c-event-delegates/ –

Cuestiones relacionadas