ほぼこれを行う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);
}
type のプロパティを定義または継承する実行中のアセンブリ内のクラスを見つけるには、次の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
予想通り。