visual valid net name example documentacion comment comentarios code c# constructor code-design

valid - C#Cómo ejecutar código después de la construcción del objeto(postconstrucción)



param name c# (9)

Como puede ver en el siguiente código, se llama al método DoStuff () antes del Init () durante la construcción de un objeto Child.

Estoy en una situación en la que tengo numerosas clases de niños. Por lo tanto, repetir una llamada al método DoStuff () directamente después de Init () en el constructor de cada niño no sería una solución elegante.

¿Hay alguna manera de que pueda crear algún tipo de constructor de publicaciones en la clase principal que se ejecutaría después del constructor del niño? De esta forma, podría llamar al método DoStuff () allí.

Si tiene alguna otra idea de diseño que pueda resolver mi problema, ¡me gustaría escucharla también!

abstract class Parent { public Parent() { DoStuff(); } protected abstract void DoStuff(); } class Child : Parent { public Child() // DoStuff is called here before Init // because of the preconstruction { Init(); } private void Init() { // needs to be called before doing stuff } protected override void DoStuff() { // stuff } }


DoStuff es abstracto. Simplemente llame a Init desde la parte superior de DoStuff.


En lugar de usar un método abstract , que requeriría implementar el método en todas las clases descendientes, puede intentar:

public class Parent { public Parent() { PostConstructor(); } protected virtual void PostConstructor() { } } public class Child : Parent { protected override void PostConstructor() { base.PostConstructor(); /// do whatever initialization here that you require } } public class ChildWithoutOverride { /// not necessary to override PostConstructor }


Sugeriría usar Factory como un patrón.

Si es posible:

1 . Empuje todas las clases de sus hijos y abstractas en un ensamble por separado .

2 . Declare los nombres de los niños como métodos internos, para que nadie fuera de esa asamblea pueda construirlos simplemente llamando a ctor.

3 . Implemente la clase Factory para construir para el tipo de objetos especificados por la persona que llama, que obviuoly evitará la invocación del método abstracto DoStuff () después de la creación real de un objeto, pero antes de devolverlo a la persona que llama.

Lo bueno de esto es que: también le dará un nivel adicional de abstracción, por lo que si en el futuro necesitará más llamadas de funciones o cualquier otro tipo de complejidad lógica, lo que necesitará, es solo agregarlos a su clase de fábrica .

Es decir.

Saludos


Qué tal esto:

abstract class Parent { public Parent() { Init(); DoStuff(); } protected abstract void DoStuff(); protected abstract void Init(); } class Child : Parent { public Child() { } protected override void Init() { // needs to be called before doing stuff } protected override void DoStuff() { // stuff } }


En las aplicaciones de WPF, puede posponer la invocación de DoStuff() con la ayuda de Dispatcher :

abstract class Parent { public Parent() { Dispatcher.CurrentDispatcher.BeginInvoke(new Action(this.DoStuff)); } private void DoStuff() { // stuff, could also be abstract or virtual } }

Sin embargo, no se garantiza que se DoStuff() inmediatamente después del constructor.


Como otros han mencionado, debe usar un patrón de fábrica.

public class Parent { public Parent() { } public virtual void PostConstructor() { } } public class Child : Parent { public override void PostConstructor() { base.PostConstructor(); // Your code here } } public void FactoryMethod<T>() where T : Parent { T newobject = new T(); newobject.PostConstructor(); }


Si tiene una lógica compleja para construir sus objetos, entonces considere el patrón FactoryMethod .

En tu caso, lo implementaría como un simple

public static Parent Construct(someParam)

método que toma algún parámetro y, en función de él, decide qué clase secundaria instanciar. Puede eliminar su llamada al método DoStuff() del constructor y llamarla dentro de Construct() en la nueva instancia.

Además, debe evitar las llamadas al método virtual / abstracto en los constructores. Vea esta pregunta para más detalles: Llamada de miembro virtual en un constructor


Corrección: según esta respuesta , no puede determinar cuándo se invoca el constructor de la clase base durante la construcción de la subclase.

Por ejemplo, esto no funciona:

public Child() // DoStuff is called here after Init // because of the overridden default constructor { Init(); base(); }

Entonces, sí, como otros han notado, si la secuencia de eventos importa, entonces la clase base necesita poder acomodar eso al declarar los métodos abstractos en orden, o (mejor aún) haciendo que la implementación de la clase infantil de DoStuff represente la secuencia de eventos:

protected override void DoStuff() { Init(); base.DoStuff(); }


Permítanme presentarles una solución general usando algunas características de C #. Tenga en cuenta que esta solución no requiere el uso de un patrón de fábrica o invocar nada después de construir el objeto, y funciona en cualquier clase con solo implementar una interfaz con un único método. Primero declaramos una interfaz que nuestras clases deberán implementar:

public interface IInitialize { void OnInitialize(); }

A continuación, agregamos una clase de extensión estática para esta interfaz y agregamos el método Initialize:

public static class InitializeExtensions { public static void Initialize<T>(this T obj) where T: IInitialize { if (obj.GetType() == typeof(T)) obj.OnInitialize(); } }

Ahora, si necesitamos una clase y todos sus descendientes para llamar a un inicializador justo después de que el objeto está completamente construido, todo lo que tenemos que hacer es implementar IInitialize y anexar una línea en el constructor:

public class Parent : IInitialize { public virtual void OnInitialize() { Console.WriteLine("Parent"); } public Parent() { this.Initialize(); } } public class Child : Parent { public Child() { this.Initialize(); } public override void OnInitialize() { Console.WriteLine("Child"); } } public class GrandChild : Child { public GrandChild() { this.Initialize(); } public override void OnInitialize() { Console.WriteLine("GrandChild"); } }

El truco es que cuando una clase derivada llama al método de extensión Initialize , eso suprimirá cualquier llamada que no se realice desde la clase real.