I want to be able to call a particular method automatically upon construction of a derived object, however I can't think how to do it. The following code illustrates. Another answer recommended OnLoad, but I am doing this for Unity on Mac and OnLoad doesn't appear to be supported by my platform. Any suggestions?
public class Parent { public Parent () { // A. Stuff to do before child constructor code runs DoThisAutomaticallyAfterConstruction(); } public void DoThisAutomaticallyAfterConstruction() { // C. In this example, this will run after A, before B. I want it to run ABC } } public class Child : Parent { public Child () : base() { // B. Stuff to do here after parent constructor code runs } }
Static constructors are called automatically, immediately before any static fields are accessed, and are generally used to initialize static class members.
If a base class has a default constructor, i.e., a constructor with no arguments, then that constructor is automatically called when a derived class is instantiated if the derived class has its own default constructor.
A constructor can call methods, yes. A method can only call a constructor in the same way anything else can: by creating a new instance. Be aware that if a method constructs a new object of the same type, then calling that method from a constructor may result in an infinite loop...
It's not possible to call the constructor two times without using reflection as it's called only once to construct the object. Instance constructors are used to create and initialize any instance member variables when you use the new expression to create an object of a class.
Unfortunately there's no built-in way to do what you want (it's a fairly-often-requested feature).
One workaround is to implement a factory pattern, where you don't create objects by calling the constructor directly, but instead implement a static method to create them for you. For example:
public class MyClass { public MyClass() { // Don't call virtual methods here! } public virtual void Initialize() { // Do stuff -- but may be overridden by derived classes! } }
then add:
public static MyClass Create() { var result = new MyClass(); // Safe to call a virtual method here result.Initialize(); // Now you can do any other post-constructor stuff return result; }
and instead of doing
var test = new MyClass();
you can do
var test = MyClass.Create();
While @Jeremy Todd's (accepted) answer works and is a widely accepted solution to the problem, it has a drawback: not very IoC and serialization friendly, since your class cannot be properly constructed using new
. Let me introduce a general solution using some C# features. Note that this solution does not require you to use a factory pattern or invoke anything after constructing the object, and it works on any class with just implementing an interface with a single method. First we declare an interface that our classes will have to implement:
public interface IInitialize { void OnInitialize(); }
Next we add a static extension class for this interface, and add the Initialize method:
public static class InitializeExtensions { public static void Initialize<T>(this T obj) where T: IInitialize { if (obj.GetType() == typeof(T)) obj.OnInitialize(); } }
Now, if we need a class and all of its descendants to call an initializer right after the object is fully constructed, all we need to do is implement IInitialize
and append a line in the 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"); } }
The trick is that when a derived class calls the extension method Initialize
, that will suppress any calls not made from the actual class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With