Как получить свойства для наследуемого класса по этому условию

У меня есть Person класс, который наследует PersonBase и этот второй класс наследует EntityBase:

public class Person : PersonBase
{        
   virtual public string FirstName { get; set; }
   virtual public string LastName { get; set; } 
}

А также

public class PersonBase : EntityBase
{        
   virtual public string GroupName { get; set; }
}

А также

public class EntityBase : IEntity
{    
   public virtual long Id { get; protected set; }
   public virtual string Error { get; protected set; }
}

Мне нужно получить список свойств Person а также PersonBase классы:

var entity = preUpdateEvent.Entity;

foreach (var item in entity.GetType().GetProperties()) //only FirstName & LastName & GroupName
{
   if (item.PropertyType == typeof(String))               
      item.SetValue(entity, "XXXXX" ,null);
} 

Сейчас GetProperties() это включает в себя: FirstName, LastName, GroupName, Id, Error но мне нужны только собственные свойства Person, а именно: FirstName, LastName, GroupName

Конечно, я использовал приведенный ниже код, но он не подходит для меня, потому что он включает только свойства Person учебный класс.

var properties = typeof(Person).GetProperties(BindingFlags.Public |
                                                  BindingFlags.Instance |
                                                  BindingFlags.DeclaredOnly);

Как я могу получить свойства, которые определены только на Person а также PersonBase классы?

4 ответа

Решение

Вот общее решение вашей проблемы в форме метода расширения:

public static PropertyInfo[] GetPropertiesUpTo<T>(this Type type, BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)
{
    return type.GetProperties(flags)
               .Where(p => p.DeclaringType == typeof(T) || p.DeclaringType.IsSubclassOf(typeof(T)))
               .ToArray();
}

Вы можете использовать это так:

var properties = typeof(Person).GetPropertiesUpTo<PersonBase>();
var properties = typeof(Person).GetProperties()
    .Where(p => p.DeclaringType == typeof(PersonBase) || p.DeclaringType == typeof(Person));

Вы должны будете найти это рекурсивно, пройдя через typeof(Person).BaseType который вернется PersonBase,

Вы не можете сказать GetProperties() "сколько" классов для получения свойств - он либо получает свойства для текущего класса и всех классов, которые он расширяет / наследует, либо (используя BindingFlags.DeclaredOnly) он может получить только свойства текущего класса.

Вы можете использовать два вызова для получения свойств:

var properties = typeof(Person).GetProperties(BindingFlags.Public |
                                                  BindingFlags.Instance |
                                                  BindingFlags.DeclaredOnly);
var parentProperties = typeof(PersonBase).GetProperties(BindingFlags.Public |
                                                  BindingFlags.Instance |
                                                  BindingFlags.DeclaredOnly);

Или фильтр по полному списку возвращается без использования BindingFlags.DeclaredOnly с использованием каждого свойства DeclaringType значение. Это может быть сделано с linq как показал Ли, или просматривая полный список свойств и используя if-statement:

List<PropertyInfo> properties = new List<PropertyInfo>();
foreach (PropertyInfo pi in typeof(Person).GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
    if ((pi.DeclaringType == typeof(PersonBase)) || (pi.DeclaringType == typeof(Person))) {
        properties.Add(pi);
    }
}
Другие вопросы по тегам