获取属性的后备字段名称

时间:2018-08-28 14:13:25

标签: c# generics reflection properties

可能是重复的,但是我找不到合适的方式来表达自己想要的东西。

是否可以使用属性本身或扩展名来获取属性返回的支持字段的名称?

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

换句话说,是否有一种方法可以像TheProperty.GetPrivateVariableName()那样以通用方式返回"VariableNameToGet"呢?

1 个答案:

答案 0 :(得分: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,但我从未尝试过。