有没有办法在所有构造函数运行后立即自动调用特定方法?

Rob*_*ing 20 c# constructor

我希望能够在构造派生对象时自动调用特定方法,但是我想不出怎么做.以下代码说明.另一个答案是OnLoad,但我在Mac上为Unity做这个,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
    }
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*odd 18

不幸的是,没有内置的方法来做你想要的(这是一个经常被要求的功能).

一种解决方法是实现工厂模式,您不通过直接调用构造函数来创建对象,而是实现静态方法来为您创建它们.例如:

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

  public virtual void Initialize()
  {
    // Do stuff -- but may be overridden by derived classes!
  }
}
Run Code Online (Sandbox Code Playgroud)

然后加:

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;
}
Run Code Online (Sandbox Code Playgroud)

而不是做

var test = new MyClass();
Run Code Online (Sandbox Code Playgroud)

你可以做

var test = MyClass.Create();
Run Code Online (Sandbox Code Playgroud)


Már*_*ssa 5

虽然@Jeremy Todd(已接受)的答案有效并且是该问题的广泛接受的解决方案,但它有一个缺点:IoC 和序列化不太友好,因为您的类无法使用new. 让我介绍一个使用一些 C# 特性的通用解决方案。请注意,此解决方案不需要您在构造对象后使用工厂模式或调用任何内容,并且它适用于任何类,只需使用单个方法实现接口即可。首先,我们声明一个我们的类必须实现的接口:

public interface IInitialize {
    void OnInitialize();
}
Run Code Online (Sandbox Code Playgroud)

接下来我们为这个接口添加一个静态扩展类,并添加 Initialize 方法:

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

现在,如果我们需要一个类及其所有后代在对象完全构造后立即调用初始化程序,我们需要做的就是IInitialize在构造函数中实现并附加一行:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

诀窍是,当派生类调用扩展方法Initialize时,将抑制任何不是来自实际类的调用。