¿Hay alguna manera de hacer esto en C#? Sé que la subclase llamará al constructor de la superclase antes de llamar a su propio constructor, pero ¿qué ocurre si tengo algún código en la superclase que solo debería ejecutarse después de haber llamado a todos los constructores de subclases?¿Cómo ejecuto algún código en una superclase después de que se hayan construido todas las subclases?
¿Cómo ejecuto algún código en una superclase después de que se hayan construido todas las subclases?
Respuesta
Una forma de lograr esto sería para ir de una construcción 2 de fase y inicializar. Por lo que la construcción de los casos y luego llama a un método initialize la que invoca la clase base de inicialización en el orden apropiado
class MyBase
{
// Only if need to do some core initialization
public MyBase()
{
}
public virtual Initialize()
{
// do some initialization stuff here
}
}
class MyDerived : MyBase
{
// Only if need to do some core initialization
public MyDerived()
{
}
public override Initialize()
{
// do some initialization stuff here
// Call the base class initialization function
base.Initialize();
}
}
Si utiliza la función de crear/inicializar de dos pasos, lo haría aconseje usar un método de fábrica o Asbtract Factory para asegurar que la semántica de inicialización no se extienda por todo el código. – LBushkin
Ok, eso no es exactamente lo que quise decir pero me ayuda a resolver el problema, ty –
class A : B
{
public A() : base()
{
base.doSomething();
}
}
class B : C
{
public B() : base()
{
}
public void doSomething() { /* ... */ }
}
class C
{
public C() { /* ... */ }
}
orden de ejecución debe ser:
- C :: ctor()
- B :: ctor()
- A :: ctor()
- B :: doSomething ()
Como dije, el método debe ejecutarse en la superclase, no en la subclase, solo está llamando al método de la superclase en la subclase. –
Sospecho que OP está buscando una solución donde la clase base pueda garantizar que se ejecute cierta inicialización después de que el tipo esté completamente instanciado. De lo contrario, cada autor de clase derivado debe asegurarse de llamar a la lógica de inicialización necesaria. – LBushkin
Eso es exactamente lo que necesito :( –
No estoy seguro de lo que quiere decir, ¿no puede simplemente llamar al código en la súper clase al final de nuestra última subclase? ¿estructor? Alternativamente, puede llamarlo directamente después de la creación de instancias.
class Program
{
static void Main(string[] args)
{
SubSub obj = new SubSub();
//obj.DoStuff();
Console.ReadLine();
}
}
class Super
{
public Super()
{
Console.WriteLine("Constructing Super");
}
public void DoStuff()
{
Console.WriteLine("Doin' stuff");
}
}
class Sub : Super
{
public Sub()
{
Console.WriteLine("Constructing Sub");
}
}
class SubSub : Sub
{
public SubSub()
{
Console.WriteLine("Constructing SubSub");
DoStuff();
}
}
Esta salida voluntad:
Constructing Super
Constructing Sub
Constructing SubSub
Doin' stuff
Lo que quiero decir es que el código podría ejecutarse después de la construcción completa del objeto en la superclase, la subclase no debería saberlo. –
Se podría hacer lo siguiente, pero es arriesgado (ver mi Editar a continuación):
public class Parent
{
public Parent()
{
Initialize();
}
protected virtual void Initialize()
{
// do stuff
}
}
public class Child : Parent
{
protected override void Initialize()
{
// do child stuff
base.Initialize();
}
}
Editar
Como se sugiere en el comentario de Terrence más adelante, este es un enfoque arriesgado porque Initialize()
se ejecutará antes de ejecutar Child
's constructor. Si hay campos inicializados en el constructor Child
, no estarán listos si son utilizados por Initialize()
. Esto podría causar errores confusos.
Una solución simple sería renunciar a la llamada principal Initialize()
y en su lugar tener las clases secundarias llamar Initialize()
. Como otros han sugerido, otra opción sería usar el patrón abstracto de fábrica.
Aquí es una solución simple que utiliza un método de fábrica estática:
class Program
{
static void Main()
{
Child.Create(() => new Child(5));
Console.ReadKey();
}
}
public abstract class Parent
{
protected virtual void Initialize()
{
Console.Write(" is the number.");
}
public static TChild Create<TChild>(Func<TChild> childGetter)
where TChild : Parent
{
var child = childGetter();
child.Initialize();
return child;
}
}
public class Child : Parent
{
private int _number;
public Child(int number)
{
_number = number;
}
protected override void Initialize()
{
Console.Write(_number.ToString());
base.Initialize();
}
}
Esto viola la recomendación contra llamadas virtuales métodos de un constructor. Este método puede llevar a rastrear errores. Ver: http://blogs.msdn.com/b/scottwil/archive/2005/01/14/353177.aspx y http : //stackoverflow.com/questions/308061/virtual ization-in-super-class-constructor – Terrence
@Terrence, gracias por su comentario. Actualizado mi respuesta. – devuxer
No hay nada integrado en el lenguaje C# que te permite hacer esto. Sin embargo, usar un patrón de creación podría soportarlo. Por ejemplo, el patrón Abstract Factory puede ser útil aquí. La fábrica base se aseguraría de que se invoque un método en la clase base recién creada una vez que se haya instanciado como el tipo de elemento secundario concreto.
¿Sabes si Castle Windsor tiene algo así? –
Esto es realmente más el dominio de una herramienta de AOP como PostSharp (que ahora me has recordado que debería haber sido incluida en mi respuesta), pero es posible que Windsor lo haga. Nunca intenté. – RationalGeek
- 1. ¿Cómo verificar que todas las tareas se hayan completado correctamente?
- 2. ¿Cómo llamar la alerta después de que se hayan realizado todas las solicitudes de Ajax?
- 3. SenTestKit: ¿limpieza después de que se hayan ejecutado TODAS las pruebas?
- 4. ¿cuál es el uso del método listo en Ember.Application? ¿Se llamará después de que se hayan inicializado todas las vistas?
- 5. Ejecutar la función después de que todas las solicitudes ajax .load() hayan finalizado
- 6. ¿Tengo que borrar setTimeouts después de que se hayan ejecutado?
- 7. cómo obtener todas las subclases de una clase en php
- 8. Cómo ejecutar código después de que se hayan manejado todos los demás eventos
- 9. seleccionar entidades de múltiples subclases que se extienden desde una superclase utilizando doctrina 2
- 10. ¿El código del constructor se agrega al código en los constructores de las subclases?
- 11. Utilizando métodos "protegidos finales" de superclase para mantener el código común para las subclases
- 12. ¿Cómo puedo forzar que un Constructor se defina en todas las subclases de mi clase abstracta?
- 13. Ejecutar código jQuery después de aplicar todas las reglas CSS
- 14. especialización de plantilla para todas las subclases
- 15. Listar todas las subclases con nombres completos
- 16. ¿Cómo ejecuto algún código python en otro proceso?
- 17. Agregar servicios después de que se haya construido el contenedor
- 18. ¿Cómo ejecuto el código DESPUÉS de que se haya cargado un formulario?
- 19. ¿Es posible obtener todas las subclases de una clase?
- 20. Creando una rama git después de que se hayan realizado cambios en el maestro
- 21. ¿Cómo puedo verificar que se hayan llamado todas mis funciones init?
- 22. ¿Cómo ejecuto una acción en drupal después de cada vez que se guarda un nodo?
- 23. En Perl/Moose, ¿cómo puedo aplicar un modificador a un método en todas las subclases?
- 24. El servidor no puede modificar las cookies después de que se hayan enviado encabezados HTTP, ¿cómo se corrigió?
- 25. Verifica que se hayan alcanzado los límites de YQL.
- 26. cómo establecer postData en jqgrid DESPUÉS de que se haya construido?
- 27. Django: ¿cómo agregar un formulario adicional a un formset después de que se ha construido?
- 28. ¿Qué evento se dispara después de que todas las vistas se dibujan por completo?
- 29. subclases de una biblioteca de código abierto
- 30. ¿Algún sitio web exitoso construido sobre Google App Engine?
¿Tiene un ejemplo de uso específico? –