Как узнать, является ли свойство автоматически реализованным свойством с отражением?

Итак, в моем случае я делаю открытие структуры класса с использованием отражения. Мне нужно выяснить, является ли свойство автоматически реализованным свойством объектом 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 + ">"));
}