2012-05-24 56 views
8

私は例があります。Activator.CreateInstanceをInterfaceで使用することはできますか?

あり
 Assembly asm = Assembly.Load("ClassLibrary1"); 
     Type ob = asm.GetType("ClassLibrary1.UserControl1"); 
     UserControl uc = (UserControl)Activator.CreateInstance(ob); 
     grd.Children.Add(uc); 

私はクラスのインスタンスを作成していますが、どのように私はいくつかのインタフェースを実装するクラスのインスタンスを作成することができますか?すなわちUserControl1ILoadインターフェイスを実装します。

U:私は後でインターフェイスにオブジェクトをキャストできますが、インターフェイスで実装されているアセンブリの種類はわかりません。

+6

あなたはインターフェースのインスタンスを作成することはできません。インターフェイスを実装するクラスを作成し、それをインターフェイスとして渡すことができます。 – Marco

+1

ILoad型のオブジェクトをインスタンス化することはできません。これはインタフェースです。 – JustinDanielson

答えて

14

これは私が数回使用したコードです。これは、特定のインターフェイスを実装アセンブリ内のすべてのタイプを見つける:

Type[] iLoadTypes = (from t in Assembly.Load("ClassLibrary1").GetExportedTypes() 
        where !t.IsInterface && !t.IsAbstract 
        where typeof(ILoad).IsAssignableFrom(t) 
        select t).ToArray(); 

その後、あなたはILoadを実装ClassLibrary1の中のすべての種類を持っています。

あなたはその後、それらのすべてのインスタンスを生成できます。

ILoad[] instantiatedTypes = 
    iLoadTypes.Select(t => (ILoad)Activator.CreateInstance(t)).ToArray(); 
+0

ありがとう、良い解決策。 –

+0

次のエラーが表示されます。 'ソースタイプ' System.Reflection.Assembly 'のクエリパターンの実装が見つかりませんでした。 'どこが見つからないのですか?' – dotNET

+1

見つけた。上記のコードの 'Load(" ClassLibrary1 ")'の後に '.GetExportedTypes();'を続けてください。 – dotNET

4

あなたが書く場合はさらに、あなたは、インターフェイスを介して、それを治療するための必要はありません。あなたは、インターフェイスのインスタンスを作成することはできませんが、

UserControl1 implements ILoad inteface

場合はILoad

ILoad uc = (ILoad)Activator.CreateInstance(ob); 
grd.Children.Add(uc); 

として結果のオブジェクトを使用することができます

UserControl1 uc = (UserControl1)Activator.CreateInstance(ob); 
grd.Children.Add(uc); 

ILoadのメンバーはcalla

+0

'ob'はまだクラスを表す型であり、インタフェースではありません。 – Guillaume

+0

@Guillaumeで構築されたオブジェクトはILoadを実装しているので、直接使用することができます。 – archil

+0

OKですが、ILoad **を実装するアセンブリではどのようにタイプを見つけることができますか? –

3

インターフェイスはインターフェイスです。それはテンプレートです。なぜインターフェースをインスタンス化したいのですか?インタフェースを実装し、そのクラスをインスタンス化します。インターフェイスをインスタンス化することはできませんが、実際には意味をなさない。

+1

もちろん、インターフェイスをインスタンス化する簡単な方法があるのは理にかなっています。 DTOを想像してみてください。行動のないPOCO。モックフレームワークでそれらを簡単に使用するために、それらをインターフェイスとして作成したいのですが、インターフェイスを実装すると、基本的に2つの同一のコードを維持する必要があります。 NServiceBusのようないくつかのフレームワークでは、「インターフェイスをインスタンス化する」ことができます。 Activatorのような機能で簡単に行うことができるとは言いませんが、私はちょうどあなたが「意味をなさない」としてこれを吹き飛ばすことはできないと言っています。 – Morten

4

「NInject」のようなIoCコンテナを使用して、必要なものを達成することができます。 インターフェイスを要求したときにコンクリートタイプを返すようにコンテナを設定できます。

2

ライブラリを使用することがプロジェクトで参照されている場合:

static public IEnumerable<Type> GetTypesFromLibrary<T>(String library) 
    { 
     var MyAsemblies = AppDomain.CurrentDomain.GetAssemblies() 
         .Where(a=>a.GetName().Name.Equals(library)) 
         .Select(a=>a); 
     var Exported = MyAsemblies 
         .FirstOrDefault() 
         .GetExportedTypes(); 
     var Asignable = Exported 
         .Where (t=> !t.IsInterface && !t.IsAbstract 
         && typeof(T).IsAssignableFrom(t)) 
         .Select(t=>t) 
         .AsEnumerable(); 
     return Asignable; 
    } 

    static public T GetInstanceOf<T>(String library, String FullClassName) 
    { 
     Type Type = GetTypesFromLibrary<T>(library) 
         .Where(t => t.FullName.Equals(FullClassName)) 
         .FirstOrDefault(); 
     if (Type != null) 
     { 
      T Instance = (T)Activator.CreateInstance(Type); 
      return Instance; 
     } 
     return default(T); 
    } 
2

受け入れ答えの唯一の問題は、あなたが持っている必要がありますということですインターフェイスを実装するアセンブリの具象クラス。

実行時に動的オブジェクトを作成し、目的のインターフェイスを実装できるCustomActivatorを作成しないようにします。

私はgithubの上に置く: https://github.com/fabriciorissetto/CustomActivator

を呼び出しは簡単です:

CustomActivator.CreateInstance<MyInterface>(); 
関連する問題