web-dev-qa-db-ja.com

特定のインターフェイスを実装するすべてのクラスを見つける方法は?

特定の名前空間の下に、インターフェイスを実装するクラスのセットがあります。 ISomethingと呼びましょう。 CClassについては知っているが、そのインターフェイスを実装するクラスについては知らない別のクラス(ISomethingと呼びましょう)があります。

そのCClassISomethingのすべての実装を探し、そのインスタンスをインスタンス化し、メソッドを実行することを望みます。

誰かがC#3.5でそれを行う方法についてアイデアを持っていますか?

66
Martin

動作するコードサンプル:

var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.GetInterfaces().Contains(typeof(ISomething))
                         && t.GetConstructor(Type.EmptyTypes) != null
                select Activator.CreateInstance(t) as ISomething;

foreach (var instance in instances)
{
    instance.Foo(); // where Foo is a method of ISomething
}

編集 CreateInstanceの呼び出しが成功するように、パラメーターのないコンストラクターのチェックを追加しました。

130
Matt Hamilton

これを使用して、ロードされたアセンブリのリストを取得できます。

Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()

そこから、アセンブリ内の型のリストを取得できます(パブリック型を想定):

Type[] types = Assembly.GetExportedTypes();

次に、オブジェクト上でそのインターフェイスを見つけることにより、各インターフェイスがそのインターフェイスをサポートしているかどうかを確認できます。

Type interfaceType = type.GetInterface("ISomething");

リフレクションを使用してこれを行うより効率的な方法があるかどうかはわかりません。

10
Mitch Denny

Linqを使用した例:

var types =
  myAssembly.GetTypes()
            .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
8
CMS
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
    if (t.GetInterface("ITheInterface") != null)
    {
        ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
        executor.PerformSomething();
    }
}
3
Kiran

次のようなものを使用して、ニーズに合わせて調整できます。

var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();

foreach (var type in types)
{
    if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
    {
        ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
        something.TheMethod();
    }
}

このコードでは、いくつかのパフォーマンス強化を使用できますが、開始点です。

2

たぶん、私たちはこのように行くべきです

foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() ) 
   instance.Execute(); 
0
bane 975