【问题标题】:Reflection: Get FieldInfo from PropertyInfo反射:从 PropertyInfo 中获取 FieldInfo
【发布时间】:2023-04-01 18:55:01
【问题描述】:

我正在使用反射进行一些动态代码生成,我遇到了一种情况,我需要获取属性的支持字段(如果有的话)才能使用其 FieldInfo 对象。

现在,我知道你可以使用

.IsDefined(typeof(CompilerGeneratedAttribute), false);

在 FieldInfo 上发现它是否是自动生成的,所以我假设自动生成字段的 Properties 也有类似的东西?

干杯,埃德

【问题讨论】:

标签: c# reflection


【解决方案1】:

属性的get_set_ 方法也将CompilerGeneratedAttributed 应用于它们。虽然通过属性没有强耦合,但自动属性的支持字段有一个命名约定:

public string Foo { get; set;}

产生一个private string <Foo>k__BackingField 成员(这里的<> 是名称的一部分,因为它们在IL 中是合法的,但在C# 中是不合法的;它们与泛型无关)。

例如,这将获得一个类中所有自动属性的列表,以及它们的支持字段:

t.GetProperties().Where(p => 
    (p.GetGetMethod() ?? p.GetSetMethod()).IsDefined(typeof(CompilerGeneratedAttribute), false))
   .Select(p => new 
   { 
      Property = p, 
      Field = t.GetField(string.Format("<{0}>k__BackingField", p.Name),
          System.Reflection.BindingFlags.NonPublic | 
          System.Reflection.BindingFlags.Instance) 
   });

【讨论】:

  • 我不确定这是否足够可靠,是否还有其他情况可以将此标志添加到方法中?
  • @Ed:没有实例可以将其添加到与属性关联的方法中。除非 C# 编译器的未来版本发生变化,否则这种方法是 100% 可靠的。
  • 此方法是否也适用于其他编译器生成的代码,还是仅适用于 C#?
【解决方案2】:

没有用于执行此操作的内置方法,因为属性的存在并不一定保证支持字段的存在。

我找到了this article,它解释了一种方法。它涉及获取属性设置器的 IL 并对其进行解析以寻找字段被设置的证据。

【讨论】:

  • 是的,我知道属性只是访问器方法的抽象,但我假设编译器会在自动生成的 get 上放置一个标志;方法,与字段相同。看来不是这样的!
  • @Ed:编译器确实将CompilerGeneratedAttribute 应用于get_set_ 方法。
  • @Adam 对不起,是的,当我阅读它时,完全跳过了你的答案的第一部分。
  • 我没有加载该博客。使用 WayBackMachine 我能够获得一个存档版本,它说代码已经移到它自己的项目中:github.com/jbevain/mono.reflection
【解决方案3】:

安德鲁是对的。

实际上,属性只是方法的“指针”,通常是由 Visual Studio 或其他高级语言生成的 getter/setter(大多数情况下)。

不过,解析 setter 并不容易。而且,由于内部设置器只是另一种普通方法,它们可以使用多个字段,或者根本不使用,甚至调用另一种方法。 或许你可以为常见的场景想出一个解决方案,但是你必须解析IL字节码。

【讨论】:

  • 他的问题似乎很清楚,他指的是自动属性,可以可靠地链接到支持字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多