インターフェイスから継承するすべてのクラスのインスタンスを取得することは可能ですか?

StackOverflow https://stackoverflow.com/questions/1204333

  •  05-07-2019
  •  | 
  •  

質問

作成している小さなプロジェクトがあり、特定のインターフェイスから継承するすべてのクラスのインスタンスを取得できるかどうかを把握しようとしています。

これは私が達成しようとしていることの簡単な例です。

public interface IExample
{
    string Foo();
}

public class Example1 : IExample
{
    public string Foo()
    {
        return "I came from Example1 !";
    }
}

public class Example2 : IExample
{
    public string Foo()
    {
        return "I came from Example2 !";
    }
}

//Many more ExampleN's go here

public class ExampleProgram
{

    public static void Main(string[] args)
    {
        var examples = GetExamples();

        foreach (var example in examples)
        {
            Console.WriteLine(example.Foo());
        }
    }

    public static List<IExample> GetExamples()
    {
        //What goes here?
    }
}

GetExamplesメソッドがIExampleインターフェイスを継承する各クラスのインスタンスを含むリストを返す方法はありますか(ハードコーディングを省略)?あなたが与えることができる洞察は非常に高く評価されるでしょう。

役に立ちましたか?

解決

参照:クラスはジェネリッククラスから派生しています

また: Reflectionを介したインターフェースの実装欲しいもの

基本的には、ターゲットアセンブリのすべての型を列挙し、インターフェイスを実装しているかどうかをテストするだけです。

他のヒント

Mattのソリューションに基づいて、次のように実装します。

public static List<IExample> GetExamples()
{
    return GetInstances<IExample>().ToList();
}

private static IEnumerable<T> GetInstances<T>()
{
    return Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => type.IsClass &&
                       !type.IsAbstract &&
                       type.GetConstructor(Type.EmptyTypes) != null &&
                       typeof (T).IsAssignableFrom(type))
        .Select(type => (T) Activator.CreateInstance(type));
}

このソリューションは、抽象クラス、派生インターフェース、デフォルト(パラメーターなし)パブリックコンストラクターのないクラスなど、インスタンス化できない型をスキップします。

そのようなことをする方法は次のとおりです。

    public static List<IExample> GetExamples()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var types = assembly.GetTypes().Where(t => t.GetInterfaces().Any(i => i == typeof(IExample))).ToList();

        List<IExample> returnMe = new List<IExample>();
        foreach (var type in types)
            returnMe.Add((IExample) Activator.CreateInstance(type));

        return returnMe;
    }

リフレクションを使用する必要があります。

Assembly.GetExecutingAssembly が出発点になります。

編集:役立つコード

Type[] types = Assembly.GetExecutingAssembly().GetTypes();
foreach(Type tp in types)
{
    if (typeof(IExample).IsAssignableFrom(tp))
    {
        if (tp.IsInterface == false)
        {
            IExample t = Activator.CreateInstance(tp) as IExample;
            Console.WriteLine(t.Foo());
        }
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top