2012-05-21 23 views
6

estoy tratando de hacer lo siguiente:Asignación dinámica de clase derivada en C#

public abstract BaseClass { 

    public virtual void ReceiveEvent(Event evt) 
    { 
     ProcessEvent(evt as dynamic); 
    } 

    private void ProcessEvent(object evt) 
    { 
     LogManager.Log(@"Received an event that is not being processed! 
         Dispatch fallback"); 
    } 
} 

public DerivedClass: BaseClass { 

    private void ProcessEvent(SpecificEvent evt) 
    { 
     LogManager.Log("Processing Event"); 
    } 
} 

SpecificEvents golpean el método de respaldo en lugar de la de la clase derivada. Uso el despacho dinámico dentro de la misma clase todo el tiempo y lo encuentro realmente útil/limpio. ¿No funcionará con las clases derivadas como se ilustra en el ejemplo anterior?

EDITAR: Parece haber algo de confusión en las respuestas. Básicamente yo uso el siguiente diseño todo el tiempo:

public class SomeClass{ 

    public void DoSomethingDispatcher(SomeObject obj) 
    { 
     ProcessObject(obj as dynamic); 
    } 

    private void DoSomething(SomeObjectType1 obj) 
    { 

    } 

    private void DoSomething(SomeObjectType2 obj) 
    { 

    } 

    private void DoSomething(SomeObjectType3 obj) 
    { 

    } 

    private void DoSomething(object obj) //fallback 
    { 

    } 
} 

funciona muy bien para cuando no conoce el tipo exacto de antemano y que no quiero utilizar una sentencia switch gran. Me pregunto si esto se puede implementar con la herencia, donde la clase base tiene el método alternativo y la clase derivada contiene todos los métodos más específicos.

+0

Supongo que se llama al ReceiveEvent en BaseClass en lugar de DerivedClass. ¿Has intentado anular el ReceiveEvent en DerivedClass? Es virtual, por lo que puede hacer 'public override void ReceiveEvent (Event evt)' Aquí hay más información sobre métodos virtuales: http://msdn.microsoft.com/en-us/library/aa645767%28v=vs.71%29. aspx – Davio

Respuesta

4

No funciona para usted porque incluso si evt se pasa dinámicamente, ProcessEvent no se declara como virtual. Esto significa que cuando se compila la llamada a ProcessEvent, se vincula a la única implementación del método que se encuentra en la clase base, y las que se encuentran en las clases derivadas nunca se ejecutarán. Además, no puede simplemente declarar su ProcessEvent como virtual, ya que la firma será diferente en las clases derivadas.

Para que el código funcione como se esperaba que sólo podría invalidar ReceiveEvent en las clases derivadas dejándolo exactamente el mismo:

public override void ReceiveEvent(Event evt) 
    { 
     ProcessEvent(evt as dynamic); 
    } 

Si desea administrar los eventos no controlada en la clase base, el cambio solo el modificador del evento Process en la clase base para proteger (de lo contrario, no se puede ejecutar cuando lo llame la versión anulada de ReceiveEvents).

+0

Sí, así es como lo tengo escrito ahora. Supongo que es la solución más cercana. Esperaba poder mover la alternativa a la clase base, pero parece que no es posible según la forma en que describes el proceso de compilación. Aclamaciones. –

+0

Oh, acabo de notar el último párrafo. ¡Le voy a dar una oportunidad! –

1

¿Cuál es el tipo de su "evt" cuando toca ProcessEvent?

Usted puede echar un vistazo a Using Type dynamic:

El tipo es un tipo estático, sino un objeto de tipo dinámico no pasa por comprobación de tipo estático. En la mayoría de los casos, funciona como si tuviera el objeto tipo .

Por lo tanto, evt no es un SpecificEvent.

+0

Estoy usando dynamic. –

+0

Primero, la dinámica se considerará como objeto. Entonces, su herencia parece ser incorrecta, sin "virtual"/"abstracto"/"anular" o incluso "nuevo" en los métodos. Puede intentar poner virtual en los métodos ProcessEvent en la BaseClass y anular en la clase DerivedClass. – kerrubin

3

Si el método no es virtual/abstract en la clase base, y el método no está marcado como override en la clase derivada, nunca funcionará.

Además, no entiendo el uso de dynamic aquí.

+0

dinámico aquí se usa como una buena forma de enrutar tipos de objetos desconocidos a sus manejadores apropiados, sin usar una instrucción switch –

1

Para obtener el comportamiento que se espera que debe reemplazar el método virtual:

public DerivedClass: BaseClass 
{ 
    private override void ReceiveEvent(Event evt) 
    { 
     // Process your event here. 
    } 
} 

Con este código, ReceiveEvent en la clase base no se llamará, por lo tanto el repliegue ProcessEvent no se llamará.

No hay ninguna razón para usar dynamic.

Cuestiones relacionadas