web-dev-qa-db-ja.com

リフレクションによるインターフェースの実装

C#でのリフレクションを通じて、インターフェイスのすべての実装を取得するにはどうすればよいですか?

39
Chethan

答えはこれです。アプリケーションドメイン全体、つまり、アプリケーションによって現在ロードされているすべてのアセンブリを検索します。

/// <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;
}
58
Steve Cooper

Assembly.GetTypes()メソッドを見てください。アセンブリ内にあるすべてのタイプを返します。返されるすべての型を繰り返し処理し、必要なインターフェイスが実装されているかどうかを確認するだけです。

そのための方法の1つは、Type.IsAssignableFromメソッドを使用することです。

これが例です。 myInterfaceはインターフェースであり、その実装を探しています。

Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
    if (myInterface.IsAssignableFrom(type))
        Console.WriteLine(type.FullName);
}

私はそれがあなたの問題を解決するための非常に効率的な方法ではないと信じていますが、少なくとも、それは始めるのに良い場所です。

5
Anton
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;
       }
  }
}

多分そのような何か....

4
Adam Driscoll

Simon Farrow によって提案されているように、これに役立つ可能性のあるいくつかの Type 拡張メソッドを次に示します。このコードは、受け入れられた回答を再構築したものにすぎません。

コード

/// <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);
}

呼び出し元のアセンブリでインスタンス化可能な実装者を取得するには、次のようにします。

var callingAssembly = Assembly.GetCallingAssembly();
var httpModules = typeof(IHttpModule).GetInstantiableImplementors(callingAssembly);

現在のAppDomainの実装者を取得するには:

var appDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var httpModules = typeof(IHttpModule).GetImplementors(appDomainAssemblies);
3
Sam

関心のあるすべてのアセンブリをループする必要があります。アセンブリから、定義されているすべての型を取得できます。 AppDomain.CurrentDomain.Assembliesを実行すると、ロードされたアセンブリのみが取得されることに注意してください。アセンブリは必要になるまで読み込まれないため、検索を開始する前にアセンブリを明示的に読み込む必要があります。

1
Hallgrim

タイプが実装するすべてのインターフェースを意味しますか?

このような:

ObjX foo = new ObjX();
Type tFoo = foo.GetType();
Type[] tFooInterfaces = tFoo.GetInterfaces();
foreach(Type tInterface in tFooInterfaces)
{
  // do something with it
}

助けてくれることを願っています。

1
Alex Duggleby