2010-11-29 10 views
26

tengo el siguiente código donde SprintServiceClient es una referencia a una WCF Service-Eliminación de controlador de eventos anónimo

public class OnlineService 
{ 
    private SprintServiceClient _client; 
    public OnlineService() 
    { 
     _client = new SprintServiceClient(); 
    } 

    public void AddMemberToTeam(MemberModel user, int projectId, Action<int> callback) 
    { 
     _client.AddMemberToTeamCompleted += (s, e) => callback(e.Result); 
     _client.AddMemberToTeamAsync(user.ToUser(), projectId); 
    } 
} 

El problema es que cada vez que se llama AddMemberToTeam que añade otra devolución de llamada a client.AddMemberToTeamCompleted

es decir, la primera vez que se llama AddMemberToTeam se llama a la devolución de llamada una vez, la segunda vez que se llama a AddMemberToTeam, la devolución de llamada se llama dos veces ect.

¿Hay alguna forma de eliminar el controlador de eventos de AddMemberToTeamCompleted una vez que se ha llamado al controlador de eventos o utilizar otro método que acepte la devolución de llamada?

+0

Para quitarlo, necesita una referencia. Suponiendo que "AddMemberToTeamCompleted" se define con la palabra clave "event" (dejando solo los operadores - = y + =), tendrá que mantener una variable con la instancia de delegado. Crear y agregarlo la primera vez, no agregar la próxima vez, eliminar al cerrar. –

+1

posible duplicado de [Anular suscripción método anónimo en C#] (http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c-sharp) – nawfal

Respuesta

53

Se puede hacer referencia a su método anónimo desde el interior de sí mismo, siempre y cuando se asigna un delegado a una variable en primer lugar:

EventHandler<SomeEventArgs> handler = null; 
handler = (s, e) => 
    { 
     _client.AddMemberToTeamCompleted -= handler; 
     callback(e.Result); 
    }; 

_client.AddMemberToTeamCompleted += handler; 

Tenga en cuenta que debe declarar la variable y asignarla por separado o el compilador la considerará no inicializada cuando la utilice dentro del cuerpo del método.

+0

Eso funciona perfectamente, gracias –

2

No hay ninguna manera,

Aparentemente Tim y Marc tienen otra solución agradable

Pero siempre puede nombrarlos, y hacer lo -= en el manejador de sucesos nombrado en este método;)

Adivinar su evento:

_client.AddMemberToTeamCompleted += OnAddMemberToTeamCompleted; 

y

public void OnAddMemberToTeamCompleted(object sender, EventArgs args) 
{ 
    _client.AddMemberToTeamCompleted -= OnAddMemberToTeamCompleted; 
    callback(e.Result) 
} 

El siguiente problema es obtener esta devolución de llamada en su oyente. Tal vez de ponerlo en una propiedad en el EventArgs (pero que se siente un poco sucia, estoy de acuerdo)

18

El truco para crear un manejador de eventos de autodesubscribe es capturar el manejador en sí mismo para que pueda usarlo en un -=. Hay un problema de declaración y asignación definida; así que no podemos hacer algo como:

EventHandler handler = (s, e) => { 
    callback(e.Result); 
    _client.AddMemberToTeamCompleted -= handler; // <===== not yet defined  
}; 

Así que en vez de inicializar null en primer lugar, por lo que la declaración es antes del uso, y tiene un valor conocido (null) antes utilizado por primera vez:

EventHandler handler = null; 
handler = (s, e) => { 
    callback(e.Result); 
    _client.AddMemberToTeamCompleted -= handler;   
}; 
_client.AddMemberToTeamCompleted += handler; 
+0

Parece que me falta algo aquí ...¿Puede alguien explicar por qué el controlador no es nulo cuando se captura su valor al crear el delegado al método anónimo? ¿No se procesa primero el lado derecho de un operador de asignación? Entonces, ¿no debería ocurrir la captura del valor del controlador * antes * de que el manejador se asigne al nuevo delegado anónimo? Sin embargo, este código parece funcionar, por lo que tengo curiosidad sobre por qué funciona en lugar de intentar eliminar un controlador nulo. ¿La captura del valor de las variables externas en el método anónimo ocurre de alguna manera después de la asignación del controlador? – reirab

+1

@reirab en C#, es la variable que se captura, no el valor actual. –

+0

Ah, vale, gracias. Sabía que el compilador de C# realmente crea un nuevo objeto que incluía el método anónimo y la variable que se captura, sin embargo, no me había dado cuenta anteriormente de que la variable en el nuevo objeto es realmente la utilizada por la clase externa, no solo una copia de eso Interesante. – reirab

Cuestiones relacionadas