Is there a way to automatically call a particular method immediately after all constructors have run?

前端 未结 4 1881
独厮守ぢ
独厮守ぢ 2021-02-12 12:54

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 a

相关标签:
4条回答
  • 2021-02-12 13:17

    Based on your example you are accomplishing ACB, you want to accomplish ABC.

    In order to run code after the child constructor, you need to make the call after B (the child constructor) you cannot call the code at A (the parent constructor) then you won't accomplish ABC.

    Move DoThisAutomaticallyAfterConstruction() at the end of the child class constructor?

    Truly a strange question though.

    0 讨论(0)
  • 2021-02-12 13:25

    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.

    0 讨论(0)
  • 2021-02-12 13:36

    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();
    
    0 讨论(0)
  • 2021-02-12 13:36

    This sounds like a good candidate for a factory. Make all the constructors private or protected, requiring consumers of your code to call the factory method when they want an instance of your object. In the factory method, you use the new operator to create the object, and then call DoThisAutomaticallyAfterConstruction() before returning the object.

    EDIT

    A factory may be a static method, or you may have a factory object. See, for example, Wikipedia on the abstract factory pattern at http://en.wikipedia.org/wiki/Abstract_factory_pattern, and the documentation for the ADO.NET DbProviderFactories at http://msdn.microsoft.com/en-us/library/wda6c36e.aspx for a real-world implementation.

    0 讨论(0)
提交回复
热议问题