Определение свойств, которые переопределяют базовые свойства или реализуют интерфейсы - PullRequest
1 голос
/ 20 июля 2010

Мне дают:

  • Класс "T", который реализует свойства, украшенные интересующими меня Атрибутами.

  • A PropertyInfo "p", представляющий свойство, принадлежащее (1) интерфейсу "I", который реализует T, (2) базовому классу "B", который T наследует или (3) сам класс T.

Мне нужно получить атрибуты, определенные (или унаследованные) для свойств в T, даже если p DeclaringType является интерфейсом, который реализует T, или классом, от которого наследуется T. Поэтому мне нужен способ добраться от p до PropertyInfo, который действительно существует на T. Таким образом, кажется, что есть 3 случая:

  1. p.DeclaringType == typeof(T)

    Это тривиальный случай. Я могу перебирать свойства T, пока не найду совпадение. Пример: * * тысяча тридцать пять

    return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    .FirstOrDefault(property => property == p)
    
  2. p.DeclaringType == typeof(I), где I - это интерфейс, который T реализует

    Это сложнее. Я обнаружил, что могу использовать InterfaceMapping, чтобы найти соответствующую реализацию p в T. Вроде как хакерский, но вот что работает:

    if (p.DeclaringType.IsInterface &&
        typeof(T).GetInterfaces().Contains(p.DeclaringType))
    {
        InterfaceMapping map = typeof(T).GetInterfaceMap(p.DeclaringType);
        MethodInfo getMethod = p.GetGetMethod();
        for (int i = 0; i < map.InterfaceMethods.Length; i++)
        {
            if (map.InterfaceMethods[i] == getMethod)
            {
                MethodInfo target = map.TargetMethods[i];
                return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .FirstOrDefault(property => property.GetGetMethod() == target);
            }
        }
    }
    
  3. p.DeclaringType == typeof(B) где B - это класс, который T наследует от

    Мне пока не удалось выяснить, как определить свойство в T, которое переопределяет виртуальное свойство p, определенное в базовом классе T B.

Так что мои вопросы

  • В случае 3 как мне найти PropertyInfo в T, который переопределяет свойство p в B?
  • Есть ли лучший способ сделать все три? Возможно, способ объединить три случая.

Ответы [ 2 ]

1 голос
/ 20 июля 2010

Я думаю, вы пропустили случай: возможно, T просто наследует свойство от B, не переопределяя его (если вы точно не знаете, что это не произойдет в вашем конкретном сценарии).

В любом случае вам просто нужно выполнить поиск свойства по имени, используя typeof(T).GetProperty, поскольку в данном классе не может быть 2 свойств с одинаковым именем (в отличие от методов, которые могут иметь несколько перегрузок). Однако вам следует остерегаться случая, когда T скрывает свойство, унаследованное от B, с использованием модификатора new. Чтобы справиться с этим случаем, вы можете проверить Attributes метода получения свойства (полученного с помощью GetGetMethod): если присутствует флаг NewSlot, он скрывает унаследованный метод получения.

0 голосов
/ 21 июля 2010

Я нашел способ ответить , дело 3 .Ключ MethodInfo.GetBaseDefinition

if (typeof(T).IsSubclassOf(p.DeclaringType))
{
    MethodInfo baseDefinition = p.GetGetMethod().GetBaseDefinition();
    return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    .FirstOrDefault(property => property.GetGetMethod().GetBaseDefinition() == baseDefinition);
}

Однако это работает только для свойств, которые были переопределены на T.

Редактировать:

Сравнивая следующее, онне имеет значения, были ли свойства переопределены или нет T:

property.GetGetMethod().GetBaseDefinition().MetadataToken == baseDefinition.MetadataToken
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...