2010-10-04 6 views
6

Estoy tratando de crear lo que estoy pensando como una clase de traducción, para que mi programa pueda hablar a una variedad de plataformas de destino. Cada plataforma será manejada por una implementación separada de una clase abstracta. He reducido las cosas por simplicidad.Implementando la implementación de eventos en clases abstractas derivadas

que tienen una clase abstracta, con un par de métodos abstractos:

abstract class ControllerBase 
{ 
    public abstract bool EnableDTMFDetection(string CallID, Party Party); 
    public abstract bool DisableDTMFDetection(string CallID, Party Party); 
} 

Posteriormente una clase (clases) que se derivan de ControllerBase, y aplicar plenamente esos métodos:

class PlatformOne : ControllerBase 
{ 
    public override bool EnableDTMFDetection(string CallID, Party Party) 
    { 
     // Do Stuff 
     return true; 
    } 

    public override bool DisableDTMFDetection(string CallID, Party Party) 
    { 
     // Do Stuff 
     return true; 
    } 
} 

Hasta ahora tan bueno. Para PlatformOne me veo obligado a definir cada uno de esos métodos, prescribiendo cómo enviaré un mensaje de salida a mi plataforma objetivo.

Son los eventos entrantes los que me han atrapado. Necesito poder subir eventos desde dentro de mis clases derivadas. Cuando agrego lo siguiente para ControllerBase:

public delegate void MyEventHandler(object sender, EventArgs e); 
    public event MyEventHandler MyEvent; 

Se compila bien, pero no puede provocar el evento desde el interior de mi clase derivada sin el error: "El evento 'ControllerBase.MyEvent' sólo puede aparecer a la izquierda lado de la mano de + = o - = (excepto cuando se usa dentro del tipo 'ControllerBase') "

Entonces, a) ¿Cómo puedo plantear mi evento desde mi clase derivada, y b) ¿alguien puede sugerir un mecanismo para imponer el cableado de eventos especificados desde mi clase derivada (a la funciones abstractas o métodos de interfaz). Gracias :) llama

+0

Parece que necesita leer cómo publicar eventos. Además, si agrega el código relacionado con "MyEvent", eso podría ayudar a responder la pregunta. – Nayan

Respuesta

10

La forma más sencilla de hacer esto es escribir un método en su clase base para elevarlo:

protected void OnMyEvent(EventArgs e) 
{ 
    // Note the copy to a local variable, so that we don't risk a 
    // NullReferenceException if another thread unsubscribes between the test and 
    // the invocation. 
    EventHandler handler = MyEvent; 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

Usted puede querer hacer que un método virtual para que pueda invalidar en clases derivadas ... depende de tu caso de uso.

Tenga en cuenta que este no es forzando una implementación de cualquier cosa en la clase derivada, pero creo que es lo que realmente desea.

+0

Jon - gracias por la respuesta - en su ejemplo, ¿dónde y cómo está sugiriendo que cree la instancia MyEvent de EventHander? –

+0

@Adrian: puede simplemente declararlo como un evento parecido a un campo en la clase base, como lo ha mostrado al final de su pregunta. –

+0

Jon - Creo que tengo cosas que funcionan ahora, y muchas gracias. Quedan dos preguntas: cuando se hace exactamente como se describe, necesito decir "var handler = MyEvent;" a diferencia de "EventHandler handler = My Event;" y, en segundo lugar, no entiendo por qué no puedo hacer esto en mi clase derivada; básicamente, una explicación para mi inicial "The Event" ControllerBase.MyEvent 'solo puede aparecer en el lado izquierdo de + = o - = "error. –

1

Cree un invocador de eventos protegidos en la clase abstracta.

protected void InvokeMyEvent(EventArgs args) 
{ 
    var handler = MyEvent; 
    if (hander != null) 
     handler(this, args); 
} 
3

El patrón estándar consiste en añadir un método virtual protegida On<EventName> a provocar un evento

protected virtual OnMyEvent(EventArgs e) { 
    var h = MyEvent; 
    if (h != null) 
     h(this, e); 
} 

También tener en cuenta que los eventos se pueden hacer abstracta o virtual:

public abstract event MyEventHandler MyEvent; 

aunque esto solo se usa generalmente en interfaces, lo que podría ser mejor para su ControllerBase según sus requisitos exactos:

public interface IController { 
    event MyEventHandler MyEvent; 
    bool EnableDTMFDetection(string CallID, Party Party); 
    bool DisableDTMFDetection(string CallID, Party Party); 
} 

public PlatformOne : IControllerBase 

    // yadda yadda... 

    public event MyEventHandler MyEvent; 

    // members of PlatformOne can invoke MyEvent as a normal delegate 
} 
Cuestiones relacionadas