如何确定是否构造了一个类(实例构造函数已完成)
本文关键字:一个 实例 已完成 构造函数 是否 何确定 | 更新日期: 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");
}
}