2012-01-16 5 views
0

У меня есть метод, который анализирует xml и создает объект определенного типа из этого xml. Все это делается с использованием дженериков, чтобы иметь общий метод для всех типов.Глубокий поиск типа объекта в экземпляре класса

Моя проблема заключается в том, что я хочу искать свойство в разных классах, используя его имя типа (не по имени). Допустим, свойство имеет тип «type1», то некоторые из определения класса объявляется ниже:

class foo1 
{ 
    type1 prop1{get;set;} 
} 

class foo2 
{ 
    foo1 prop2{get;set;} 
} 

class foo3:foo2 
{ 
    type2 prop3{get;set;} 
} 

Для всех указанных выше заявленных классов, если я создаю объекты, то я хочу, чтобы получить доступ к type1 типизированные свойства для каждого экземпляра вышеупомянутые классы, то есть я должен был бы получить стоимость имущества, объявленного как type1, из объектов foo1, foo2, foo3 классов. Мне действительно нужен общий способ сделать это, поскольку классы могут увеличиваться.

ответ

1

Вот один из способов: почти сделать это. Отсутствует то, что использование рефлексии BindingFlags.FlattenHierarchy не возвращает частные методы родительских классов. Маркировка этих типов как защищенных или общедоступных позволит решить эту проблему. (. Вы можете также вручную переместить базовые классы для чтения частных пользователей)

Если вы хотите, чтобы найти все типы в сборке, декларировать свойство данного типа, вы могли бы написать метод, как:

// using System.Reflection 

public IEnumerable<Type> GetTypesWithPropertyOfType(Assembly a, Type t) 
{ 
    BindingFlags propertyBindingFlags = BindingFlags.Public 
             | BindingFlags.NonPublic 
             | BindingFlags.Instance 
             | BindingFlags.FlattenHierarchy; 

    // a property is kept if it is assignable from the type 
    // parameter passed in    
    MemberFilter mf = (pi, crit)=> 
      (pi as PropertyInfo) 
      .PropertyType 
      .IsAssignableFrom(t); 

    // a class is kept if it contains at least one property that 
    // passes the property filter. All public and nonpublic properties of 
    // the class, and public and protected properties of the base class, 
    // are considered 
    Func<Type, bool> ClassFilter = 
     c=>c.FindMembers(MemberTypes.Property, propertyBindingFlags, mf, null) 
      .FirstOrDefault() != null; 

    // return all classes in the assembly that match ClassFilter 
    return 
     a.GetTypes() 
     .Where(c=>c.IsClass) 
     .Where(ClassFilter); 
} 

Чтобы найти классы в исполняющей сборке, которые определяют или унаследовать свойство типа type1, можно было бы назвать:

var v = GetTypesWithPropertyOfType(
      Assembly.GetExecutingAssembly(), 
      typeof(type1)); 

    foreach (var n in v) Console.WriteLine(n.FullName); 

Это печатает foo1. Если ваш код, определяющий классы Foo пересматривается (а) сделать foo1.prop1 публично или защищены, и (б) сделать foo2 наследоваться от foo1, то выше код печатает:

foo1 
foo2 
foo3 

, как и ожидалось.

+0

Как изменить приведенный выше метод, чтобы получить значение свойства, которое имеет тип «type1».? Пожалуйста, дайте мне знать. Мое намерение - получить значения экземпляра любого класса. – rinks

+0

Эй, у меня есть другое решение (не рефлексивный подход), поскольку я считаю, что слишком много усилий для инвестиций. Но спасибо за помощь. – rinks

Смежные вопросы