Вот один из способов почти сделать это. Чего не хватает, так это того, что при использовании отражения 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, изменен на (a) сделать foo1.prop1
общедоступным или защищенным и (b) сделать foo2
наследованным от foo1
, то приведенный выше код выдает:
foo1
foo2
foo3
как и ожидалось.