Итак, в моем случае я делаю открытие структуры класса с использованием отражения. Мне нужно выяснить, является ли свойство автоматически реализованным свойством объектом PropertyInfo. Я предполагаю, что API отражения не раскрывает такую функциональность, потому что авто-свойства зависят от С#, но есть ли какие-либо способы обхода этой информации?
Как узнать, является ли свойство автоматически реализованным свойством с отражением?
Ответ 1
Вы можете проверить, отмечен ли метод get
или set
атрибутом CompilerGenerated
. Затем вы можете комбинировать это с поиском частного поля, которое помечено атрибутом CompilerGenerated
, содержащим имя свойства и строку "BackingField"
.
Может быть:
public static bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(
this PropertyInfo info
) {
bool mightBe = info.GetGetMethod()
.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
)
.Any();
if (!mightBe) {
return false;
}
bool maybe = info.DeclaringType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.Name.Contains(info.Name))
.Where(f => f.Name.Contains("BackingField"))
.Where(
f => f.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
).Any()
)
.Any();
return maybe;
}
Это не дурацкое доказательство, довольно хрупкое и, вероятно, не переносное, скажем, Моно.
Ответ 2
Это должно сделать:
public static bool IsAutoProperty(this PropertyInfo prop)
{
return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Any(f => f.Name.Contains("<" + prop.Name + ">"));
}
Причина в том, что для авто-свойств свойство Name
подстановки FieldInfo
будет выглядеть так:
<PropertName>k__BackingField
Так как символы <
и >
не отображаются для нормальных полей, поле с таким типом имен указывает на поле поддержки авто-свойства. Как говорит Джейсон, его хрупкое все еще.
Или сделать это чуть быстрее,
public static bool IsAutoProperty(this PropertyInfo prop)
{
if (!prop.CanWrite || !prop.CanRead)
return false;
return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Any(f => f.Name.Contains("<" + prop.Name + ">"));
}