C# How to execute code after object construction (

2019-02-16 03:53发布

As you can see in the code below, the DoStuff() method is getting called before the Init() one during the construction of a Child object.

I'm in a situation where I have numerous child classes. Therefore, repeating a call to the DoStuff() method directly after Init() in the constructor of each child wouldn't be an elegant solution.

Is there any way I could create some kind of post constructor in the parent class that would be executed after the child's constructor? This way, I could call to the DoStuff() method there.

If you have any other design idea which could solve my problem, I'd like to hear it too!

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
    }
}

9条回答
冷血范
2楼-- · 2019-02-16 04:45

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.

查看更多
冷血范
3楼-- · 2019-02-16 04:46

As others have mentioned, you should use a Factory Pattern.

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();
}
查看更多
你好瞎i
4楼-- · 2019-02-16 04:48

Rather than using an abstract method, which would require you to implement the method in all descendant classes, you might try:

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 
}
查看更多
登录 后发表回答