C# でリフレクションを介してインターフェイスのすべての実装を取得するにはどうすればよいですか?
6 に答える
答えはこれです。アプリケーション ドメイン全体、つまり、アプリケーションによって現在読み込まれているすべてのアセンブリを検索します。
/// <summary>
/// Returns all types in the current AppDomain implementing the interface or inheriting the type.
/// </summary>
public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
return AppDomain
.CurrentDomain
.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => desiredType.IsAssignableFrom(type));
}
このように使用されます。
var disposableTypes = TypesImplementingInterface(typeof(IDisposable));
また、この関数で実際の具象型を検出することもできます。つまり、抽象、インターフェイス、ジェネリック型定義を除外します。
public static bool IsRealClass(Type testType)
{
return testType.IsAbstract == false
&& testType.IsGenericTypeDefinition == false
&& testType.IsInterface == false;
}
メソッドを見てくださいAssembly.GetTypes()
。アセンブリ内にあるすべてのタイプを返します。あなたがしなければならないのは、返されたすべての型を繰り返し処理し、それが必要なインターフェースを実装しているかどうかを確認することです。
そのための方法の1つは、メソッドを使用Type.IsAssignableFrom
することです。
これが例です。myInterface
は、検索している実装のインターフェースです。
Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
if (myInterface.IsAssignableFrom(type))
Console.WriteLine(type.FullName);
}
私はそれがあなたの問題を解決するための非常に効率的な方法ではないと信じていますが、少なくとも、それは始めるのに良い場所です。
Assembly assembly = Assembly.GetExecutingAssembly();
List<Type> types = assembly.GetTypes();
List<Type> childTypes = new List<Type>();
foreach (Type type in Types) {
foreach (Type interfaceType in type.GetInterfaces()) {
if (interfaceType.Equals(typeof([yourinterfacetype)) {
childTypes.Add(type)
break;
}
}
}
多分そのようなもの....
Here are some Type
extension methods that may be useful for this, as suggested by Simon Farrow. This code is just a restructuring of the accepted answer.
Code
/// <summary>
/// Returns all types in <paramref name="assembliesToSearch"/> that directly or indirectly implement or inherit from the given type.
/// </summary>
public static IEnumerable<Type> GetImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
var typesInAssemblies = assembliesToSearch.SelectMany(assembly => assembly.GetTypes());
return typesInAssemblies.Where(abstractType.IsAssignableFrom);
}
/// <summary>
/// Returns the results of <see cref="GetImplementors"/> that match <see cref="IsInstantiable"/>.
/// </summary>
public static IEnumerable<Type> GetInstantiableImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
var implementors = abstractType.GetImplementors(assembliesToSearch);
return implementors.Where(IsInstantiable);
}
/// <summary>
/// Determines whether <paramref name="type"/> is a concrete, non-open-generic type.
/// </summary>
public static bool IsInstantiable(this Type type)
{
return !(type.IsAbstract || type.IsGenericTypeDefinition || type.IsInterface);
}
Examples
To get the instantiable implementors in the calling assembly:
var callingAssembly = Assembly.GetCallingAssembly();
var httpModules = typeof(IHttpModule).GetInstantiableImplementors(callingAssembly);
To get the implementors in the current AppDomain:
var appDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var httpModules = typeof(IHttpModule).GetImplementors(appDomainAssemblies);
タイプが実装するすべてのインターフェースを意味しますか?
このような:
ObjX foo = new ObjX();
Type tFoo = foo.GetType();
Type[] tFooInterfaces = tFoo.GetInterfaces();
foreach(Type tInterface in tFooInterfaces)
{
// do something with it
}
助けてくれることを願っています。
関心のあるすべてのアセンブリをループする必要があります。アセンブリから、定義されているすべてのタイプを取得できます。AppDomain.CurrentDomain.Assembliesを実行すると、ロードされたアセンブリのみが取得されることに注意してください。アセンブリは必要になるまでロードされないため、検索を開始する前にアセンブリを明示的にロードする必要があります。