如何在C#中获取对象初始化的类名

3

我有几个类,假设它们是:

public class A
{
  public void SomeAction()
  {
    Debug.Write("I was declared in class: and my name is:");
  }
}

并且

public class B
{
  public static A myClass = new A();
}

public class C
{
  public static A myClass = new A();
}

public class D
{
  public static A myClass = new A();
}

我希望类A中的"SomeAction"函数能够打印出它所在的类。
例如,在另一个类中我调用了"C.myClass.SomeAction();",它会打印出"I was declared in class C my name is myClass"。
我希望这样说起来有意义。
我之所以这样做是为了在自动化测试中进行调试。我知道这不是最好的方法,但这是业务需求。

你可以在类上添加一个字符串属性,用于保存"初始化位置",然后在实例化对象之后立即设置该属性。不确定是否有更好的方法,但这是一种方法。 :P - eddie_cat
或者您可以使用继承。B,C和D不再拥有A的实例,而是成为A的实例。 - Bill Gregg
5
我理解这不是做事情的最佳方式,但这是业务的要求。- 我喜欢这句话 :) - ColinE
这在静态方法中不起作用。 - Festivejelly
不要紧,它不应该是静态的。 - Festivejelly
3个回答

7

可以在不使用继承或传递对象的情况下满足此要求;我们可以通过检查堆栈,在构造函数的内部获取调用构造函数的类的名称。

public class A
{
    private string _createdBy;

    public void SomeAction()
    {
      Console.WriteLine("I was declared in class [{0}]", _createdBy);
    }

    public A()
    {
      var stackFrame = new StackFrame(1);
      var method = stackFrame.GetMethod();
      _createdBy = method.DeclaringType.Name;
    }
}

就性能而言,我认为你不会创建许多这些对象的实例。你也可以基于是否进行DEBUG构建或其他设置来决定,这样在生产可执行文件中就完全跳过这些内容。


@Jonkers,注意了,这种方法可以用来进行一些测试或者记录器,但是慢且不太合法。 - Sinatr
它仅用于测试自动化。它基本上生成日志文件,供“非技术”测试人员在测试失败时查看,因为他们没有Visual Studio许可证。不过还是谢谢你的提示。 - Festivejelly
能否使用相同的StackFrame来获取定义类的“名称”?例如,如果我将类的实例初始化为“myA”,我可以使用stackframe来获取它吗? - Festivejelly
@Jonkers,您不能使用StackFrame来实现此目的。请考虑到不同名称的许多不同变量可以引用一个单独的A实例。 - Jay

2

由于您在其他类中只引用了 A 类的实例,我认为除了像 eddie_cat 已经提到的那样设置一个对创建 A 类型的类型的引用之外,没有其他方法。您可以这样做:

public class B
{
  public static A myClass = new A(typeof(B));
}

然后你的A类会是这样:

public class A
{
  // store the parent type
  private Type mParentClass; 

  // provide parent type during construction of A
  public A(Type parentClass)
  {
     mParentClass = parentClass;
  }   

  // note that method cannot be static anymore, since every instance of A might 
  // have a different parent
  public void SomeAction()
  {
     // access field where parent type is stored.
     Debug.Write("I was declared in class: {0} and my name is:",mParentClass.Name);
  }
}

无论出于何种原因,您需要知道实例的父级(持有者或创建者),都应该按照此答案建议的方式完成:通过构造函数或属性传递引用(或至少类型)到父级(属性-因为我喜欢对象初始化程序,尽管它不能保证父级将被设置,但这种情况可以单独处理,并且实际上可能是想要的)。不要使用一些肮脏(而且慢)的堆栈操作。 - Sinatr
1
我不关心速度。这不是性能关键。 - Festivejelly

1
我认为你有两个选择。要么在A中设置属性,要么从A继承。就个人而言,我更喜欢从A继承,因为这样A就可以直接使用GetType()。
public class A
{
     public void SomeMethod()
     {
          Debug.Write(string.Format("I was declared in class: {0}",this.GetType()));
     }
}

public class B : A
{


}

var instanceOfB = new B();
instanceOfB.SomeMethod();

4
除了用继承来表示“是一种”的关系之外,将其用于其他任何目的都不是一个好主意。 - dcastro
this.GetType() 只会获取类 A 的类型 - Festivejelly
2
@Jonkers 不,它不会。 - Servy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接