如何确定是否构造了一个类(实例构造函数已完成)

本文关键字:一个 实例 已完成 构造函数 是否 何确定 | 更新日期: 2023-09-27 18:08:07

我有一个基类,它有一个由派生类执行的方法。该方法由派生类的构造函数及其中的一些方法或属性引发。我需要确定它是否来自派生类的实例构造函数内部或之后(在运行时)。

下面的例子解释了我需要什么:

public class Base
{
    public Base()
    {
    }
    protected void OnSomeAction(object sender)
    {
        // if from derived constructor EXIT, else CONTINUE
    }
}
public class Derived : Base
{
    public void Raise()
    {
        base.OnSomeAction(this); // YES if not called by constructor
    }
    public Derived()
    {
        base.OnSomeAction(this); // NO
        Raise(); // NO
    }
}
class Program
{
    static void Main(string[] args)
    {
        var c = new Derived(); // NO (twice)
        c.Raise(); // YES
    }
}

问题是我不能更改签名或参数,因为我不能更改派生类。基本上,我在想的是确定派生类(发送方)是否完全构造。

所以实现是这样的。我不能在基类中进行破坏派生类的更改。我只能更改基类:/

这在某种程度上是可能的,好还是坏?不幸的是,即使是一些反射魔法或类似的黑客方法也很受欢迎,因为这是必须的:/.

谢谢!

如何确定是否构造了一个类(实例构造函数已完成)

这在某种程度上是可能的吗?

是的

好还是不好?

。但是你已经知道了。

尽管如此,这里有一种方法可以做到这一点。

protected void OnSomeEvent( object sender, EventArgs e )
{
    var trace = new StackTrace();
    var frames = trace.GetFrames();
    for ( int idx = 0; idx < frames.Length; idx++ )
    {
        MethodBase method;
        method = frames[idx].GetMethod();
        if ( method.ReflectedType == typeof(Derived) && method.IsConstructor )
        {
            return;
        }
    }
    /* Perform action */
}

好,干净,合适的方式-不!恐怕不行。

这无疑会导致痛苦和折磨,也许。

把这个放到你的OnSomeEvent处理器中:

var whoCalledMe = new StackTrace().GetFrame(1).GetMethod().Name;
如果从构造函数调用

,将调用.ctor;如果从Raise方法调用

,将调用Main

实例:http://rextester.com/rundotnet?code=DBRLC84297

我将您的(非常严格的)约束解释为您不能更改方法签名,也许不能添加实例字段,但是您允许代码更改和静态字段。如果是这样,我的方法包括设置一个静态的"fromDerivedConstructor"变量,并在适当的时候对它进行测试。(为了使代码线程安全,该变量被设置为线程静态。下面的程序打印

NO
NO
YES

请求:-)

using System;
using System.Diagnostics;
namespace ConsoleApplication33 {
  public class Base {
    [ThreadStatic]
    protected static bool fromDerivedConstructor;
    public Base() {}
    protected void OnSomeAction(object sender) {
      // if from derived constructor EXIT, else CONTINUE
      if(fromDerivedConstructor) {
        Debug.WriteLine("NO");
        return;
      }
      Debug.WriteLine("YES");
    }
  }
  public class Derived : Base {
    public void Raise() {
      base.OnSomeAction(this); // YES if not called by constructor
    }
    public Derived() {
      fromDerivedConstructor=true;
      try {
        base.OnSomeAction(this); // NO
        Raise(); // NO
      } finally {
        fromDerivedConstructor=false;
      }
    }
  }
  internal class Program {
    private static void Main(string[] args) {
      var c=new Derived(); // NO (twice)
      c.Raise(); // YES
    }
  }
}

这是一个奇怪的问题,不能改变派生,但可以改变基数?是吗?

这里有一个非常简单的解决方案(我觉得很脏):

public class Base
{
    private event EventHandler SomeEvent;
    private int initCount = 0;
    public Base()
    {
    }
    protected void OnSomeEvent(object sender, EventArgs e)
    {
        // if from derived constructor EXIT
        switch (initCount)
        {
            case 0:
                initCount += 1;
                Console.WriteLine("NO");
                return;
            case 1:
                initCount += 1;
                this.SomeEvent += new EventHandler(OnSomeEvent);
                Console.WriteLine("NO");
                return;
        }
        //  else CONTINUE
        Console.Write("YES");
    }
}