【问题标题】:Getting backing field name of a property获取属性的支持字段名称
【发布时间】:2019-02-03 05:07:03
【问题描述】:

可能是重复的,但我找不到正确表述我正在寻找的内容的方法。

有没有办法使用属性本身或扩展来获取属性返回的支持字段的名称?

private string VariableNameToGet;
public string TheProperty {get => VariableNameToGet; set {VariableNameToGet = value;}}

换句话说,有没有办法以通用方式返回 TheProperty.GetPrivateVariableName() 之类的东西?

【问题讨论】:

  • 不容易。问题是:你为什么需要它? (一种方法是深入研究属性获取方法 (get_TheProperty) 并提取此信息。但这些可能很复杂,实际上可能不仅仅是返回 X;)。你到底想做什么?
  • 您正在寻找所谓的支持字段。不过,我不确定你是否可以。
  • 属性只是 getter 和 setter 方法的语法,这意味着它们不必有实际的支持字段。他们可以只返回常量值。所以做一些通用的事情是没有意义的。如果出于某种原因需要,只公开该字段的名称会更有意义。
  • @DennisKuypers 我很想知道这是否可能,因为我不熟悉深度反射的东西和“低级 c#”。我目前有解决该问题的方法。所以我主要说个人知识。
  • 顺便说一句,您可能还拥有甚至没有支持字段的自动属性。例如:public string TheProperty { get; set; }。恐怕你的问题没有任何意义。

标签: c# generics reflection properties


【解决方案1】:

您可以使用Module.ResolveMember 方法获取字段信息

假设我们需要得到System.ComponentModel.BrowsableAttribute.Browsable的支持字段

// get property info
PropertyInfo property = typeof(BrowsableAttribute).GetProperty("Browsabe");

// Need getter, because setter is missing
MethodInfo getter = property.GetGetMethod();

// Now we should get MSIL bytes stream that represents operations
byte[] bytes = getter.GetMethodBody().GetILAsByteArray();

/* IL looks like this
IL_0000: ldarg.0
IL_0001: ldfld bool System.ComponentModel.BrowsableAttribute::'<Browsable>k__BackingField'
IL_0006: ret
*/

// Knowing that field token is Int32 and it's located at offset=2 we can get it
int fieldReference = BitConvert.ToInt32(bytes, 2);

// Last part is to get actual FieldInfo
var field = (FieldInfo)property.DeclaringType.Module.ResolveMember(fieldReference);

// Now we have access to field's backing field!
Console.WriteLine(field.Name);

这个解决方案远非完美:它假设属性是由 Roslyn 编译器生成的,并且使用了自动实现的属性。如果有人手动实现了属性,我们可能会崩溃,因为代码大小应该是 7。可能会在未来版本的运行时中断或在以前的版本中不起作用(我在 net5 上测试过)

更好的解决方案是使用 Mono.Cecil,但我从未尝试过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多