C# 是否有一种方法可以在所有构造函数运行后立即自动调用特定方法?

C# 是否有一种方法可以在所有构造函数运行后立即自动调用特定方法?,c#,constructor,C#,Constructor,我希望能够在构造派生对象时自动调用特定的方法,但是我想不出怎么做。下面的代码说明了这一点。另一个答案建议使用OnLoad,但我是为Unity在Mac上这样做的,我的平台似乎不支持OnLoad。有什么建议吗 public class Parent { public Parent () { // A. Stuff to do before child constructor code runs DoThisAutomaticallyAfterCons

我希望能够在构造派生对象时自动调用特定的方法,但是我想不出怎么做。下面的代码说明了这一点。另一个答案建议使用OnLoad,但我是为Unity在Mac上这样做的,我的平台似乎不支持OnLoad。有什么建议吗

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

根据您的示例,您正在完成ACB,您希望完成ABC

为了在子构造函数之后运行代码,需要在B(子构造函数)之后进行调用。如果不能在A(父构造函数)处调用代码,则无法完成ABC

在子类构造函数的末尾移动
DoThisAutomaticallyAfterConstruction()


这确实是一个奇怪的问题。

这听起来像是一个很好的工厂候选人。将所有构造函数设置为私有或受保护,要求代码使用者在需要对象实例时调用工厂方法。在factory方法中,使用
new
操作符创建对象,然后在返回对象之前调用
DoThisAutomaticallyAfterConstruction()

编辑


工厂可以是静态方法,也可以是工厂对象。例如,请参阅Wikipedia中的抽象工厂模式,以及ADO.NET DBProviderFactorys中的文档,以了解真实世界的实现。

不幸的是,没有内置的方法来实现您想要的功能(这是一个经常请求的功能)

一种解决方法是实现工厂模式,在这种模式中,您不直接调用构造函数来创建对象,而是实现一个静态方法来为您创建对象。例如:

public class MyClass
{
  public MyClass()
  {
    // Don't call virtual methods here!
  }

  public virtual void Initialize()
  {
    // Do stuff -- but may be overridden by derived classes!
  }
}
然后添加:

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;
}
而不是做

var test = new MyClass();
你能行

var test = MyClass.Create();
尽管@Jeremy Todd的(公认的)答案有效,并且是一个被广泛接受的问题解决方案,但它有一个缺点:对IoC和序列化不太友好,因为您的类无法使用
new
正确构造。让我介绍一个使用一些C#特性的通用解决方案。请注意,此解决方案不要求您在构造对象后使用工厂模式或调用任何东西,并且它只需使用单个方法实现接口即可在任何类上工作。 首先,我们声明一个类必须实现的接口:

public interface IInitialize {
    void OnInitialize();
}
接下来,我们为该接口添加一个静态扩展类,并添加Initialize方法:

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

诀窍在于,当派生类调用扩展方法Initialize时,这将抑制任何不是从实际类发出的调用。

不幸的是,在未密封的类中,这不一定起作用,因为更多的派生类可以在子构造函数完成执行后进行进一步的初始化,所以在构造函数中调用虚拟成员仍然不安全。@JeremyTodd-如果是这样的话,我们需要OP提供更多信息。我在回答这篇文章中的信息。在普通代码中这很奇怪,但在处理UI代码时,这通常是必要的。但正如作者所说,通常我们只使用OnLoad事件。@JeremyTodd,注意这不是一个虚拟方法调用,该方法不是虚拟的。(这可能是一个模板方法模式,可能会调用其他虚拟方法,我同意。)但是,您的观点仍然成立,进一步派生的类孙子不会希望Child启动此方法。@AnthonyPegram-如果这是OP的意图,就不提其他类。这对我来说是代码味道。基类不应该与派生类有关。此外,构造函数应该设置对象的初始化状态。这很有意义。非常感谢。啊,太棒了!我听说过工厂,但这有助于我更深入地理解它们。@RobinKing请参阅我编辑的答案,以获得有关工厂模式的更多细节的一些提示。静态工厂方法是一种简单的方法,但有些人更喜欢使用工厂对象(某些情况下需要使用它们)。这是一篇非常古老的文章,但将构造函数更改为
private
,可能会很有用,这将迫使客户机使用工厂。
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");
    }
}