Как узнать, является ли свойство автоматически реализованным свойством с отражением? - PullRequest
25 голосов
/ 05 февраля 2010

Так что в моем случае я делаю открытие структуры класса, используя отражение.Мне нужно уметь выяснить, является ли свойство автоматически реализуемым свойством объекта PropertyInfo.Я предполагаю, что API отражения не предоставляет такой функциональности, потому что авто-свойства зависят от C #, но есть ли способ обойти эту информацию?

Ответы [ 2 ]

22 голосов
/ 05 февраля 2010

Вы можете проверить, помечен ли метод 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;
    }

Это не надежно, довольно хрупко и, вероятно, не переносимо, скажем, в Mono.

12 голосов
/ 12 мая 2013

Это должно сделать:

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 + ">"));
}
...