使用反射从父类获取自有属性名称

4

在调用当前类的类中,是否有可能获取当前类所分配给的属性名称?

假设我有三个类:

class Parent1
{
   public Child myName;

   public void Foo()
   {
      myName.Method();
   }
}

class Parent2
{
   public Child mySecondName;

   public void Foo()
   {
      mySecondName.Method();
   }
}

class Child
{
   public void Method()
   {
      Log(__propertyName__);
   }
}

我想在从Parent1调用Method时记录值myName,并在从Parent2调用Method时记录值mySecondName。是否可以使用反射实现此功能,而不是通过传递字符串名称作为参数(我仅想将其用于调试目的,不希望以任何方式链接这些类)?请注意保留HTML标记。

你不能通过反射来实现它,但是你可以使用表达式树来实现。参考链接 - James
@James 这可能适用于提供给方法的参数 - 在这种情况下,OP想要包含对所调用类的引用的变量的名称。使用表达式树仍然可能吗? - C.Evenhuis
@C.Evenhuis 可能不能直接实现,但你可以编写一个 Log 方法,该方法接受变量名作为参数 - 这里有一个很好的例子(https://dev59.com/F3E85IYBdhLWcg3w3Xv6)。 - James
@James 在 Method() 方法内部,this 等于该变量的值 - 我正在尝试使用您提供的链接更改我的示例,但它们都需要提供该变量。 - C.Evenhuis
1
@C.Evenhuis 是的,这引发了关于设计的问题。OP希望记录“this”在“Parent1”中声明的变量名 - 我认为这个概念是有缺陷的。Parent1 应该是记录器,而不是Child - James
@James:我只是试图找到应用程序中的一个错误,这只是暂时的。如果我想从另一侧进行记录,那么有太多的地方可以放置记录器。 - Adassko
3个回答

3

使用 StackTrace,您至少可以获取调用的方法和类:

System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace();
Type calledFromType = trace.GetFrame(1).GetMethod().ReflectedType;

这将给你Parent1类型。

我认为没有办法获得调用方法的变量名。

当然,您可以枚举calledFromType的所有字段和属性,并查看其中是否有一个是Child类型,但您将无法保证在调用时实际使用了该字段或属性。


1
请注意,1)使用StackTrace非常昂贵,2)根据您的构建(DEBUG / RELEASE),由于编译器的优化,您可能会错过一些东西。http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx。 - Maarten

3

无法使用反射实现,原因如下:

  1. 您的实例状态没有与特定“所有者”相关的内容。

  2. 可以从具有属性访问权限的任何位置调用您的代码,因此堆栈跟踪不会可靠地返回任何有用信息。

  3. 对于您类的实例的引用可以存储在任意数量的位置,包括方法调用的变量和参数中。

基本上,不行。你最好能够“告诉”它在哪里,即使这样,您仍然会遇到引用副本的问题。


2
class Child
    {
        public void Method()
        {
            StackFrame sf = new StackFrame(1);
            var type = sf.GetMethod().ReflectedType;

            var field = type.GetFields().FirstOrDefault(i => i.FieldType == typeof(Child));

            Log(field.Name);
        }
    }

请注意,1)使用StackFrame非常昂贵,2)根据您的构建(DEBUG / RELEASE),由于编译器的优化,您可能会错过一些东西。请参阅http://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe.aspx。 - Maarten
你无法保证该字段是否被调用。在Parent1中,他可以调用new Parent2().mySecondName.Method(),而你的代码将返回"myFirstName"。 - C.Evenhuis
同意两位评论者的观点,当然这并不是问题的通用解决方案。 - Lev

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