2012-02-01 2 views
2

ソリューションフォルダ内の複数のアセンブリからインターフェイスを実装するインスタンス化されたクラスの列挙を取得したいと思います。いくつかのアセンブリ間でインターフェイスを実装するオブジェクトを取得します。

(これは理にかなっている場合)私は、次のフォルダ構造を有する:

したがって
Solution 
    -SolutionFolder 
     - Project1 
      - class implementing interface I would like to find 
      - other classes 

     - Project2 
      - class implementing interface I would like to find 
      - other classes 

    -MainProject 
     - classes where my code is running in which I would like to retrieve the list of classes 

、実装されているインタフェースがISettingsである場合、私はそのインターフェイスのIEnumerable<ISettings>参照インスタンス化オブジェクトを希望。

これまでのところ、私は知られているクラス名からインターフェイスを実装するクラスを取得するためにリフレクションを使用している

IEnumerable<ISettings> configuration = 
       (from t in Assembly.GetAssembly(typeof(CLASSNAME-THAT-IMPLEMENTs-INTERFACE-HERE)).GetTypes() 
       where t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null 
       select (ISettings)Activator.CreateInstance(t)).ToList(); 

が、これは、単一のアセンブリであり、私は実際にクラス名を知ることができません。

リフレクションを使用してこれを達成できますか、それとももっと必要なものがありますか?

答えて

0

解決方法この問題を解決するには、ソリューションフォルダ内の各プロジェクトのポストビルドイベントを設定して、アセンブリをメインプロジェクトのbinフォルダのbinフォルダにコピーします。

ポストビルドイベントはに類似した:

copy "$(TargetPath)" "$(SolutionDir)MainProjectName\bin" 

それから私は、このbinディレクトリ(彼のソリューションのポストのためのダーリンにクレジットhere)からアセンブリファイル名を取得するには、次を使用:

string[] assemblyFiles = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"), "*.dll"); 

IEnumerable<ISettings> configuration = assemblyFiles.Select(f => Assembly.LoadFrom(f)) 
       .SelectMany(a => a.GetTypes()) 
       .Where(t => t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null) 
       .Select(t => (ISettings)Activator.CreateInstance(t)); 

は、それから使用インターフェイスISettingsを実装するオブジェクトの実装を取得しました

これにより、メインプロジェクトを再コンパイルせずに設定を実装するプロジェクトを追加できます。

また、私が調べた1つの代替案は、MEFを使用することでした。ここで紹介はhereです。

1

AppDomainにロードされているアセンブリについてのみ話している限り(これは、後で実行するために必要なものです)、次のようなものを使用して反復処理することができます。

AppDomain.CurrentDomain 
     .GetAssemblies().ToList() 
     .ForEach(a => /* Insert code to work with assembly here */); 

それとも、彼らは違うのAppDomainにロードされている場合は、上記のAppDomain.CurrentDomainの代わりにインスタンスを使用することができます。

+0

ありがとうございました。しかし、私のアセンブリは最初にアプリケーションドメインにロードされず、メインプロジェクトの再コンパイルを避けながら、追加のアセンブリをプラグインする必要があるかもしれません。(私が謝った最初の質問ではわかりませんでした。 – Dangerous

+0

あなたの質問のコード、私の答えのコード、実行時の 'Assembly.Load'の組み合わせを使ってアセンブリをあなたのappdomainに動的に読み込むことができます。あなたのプラグインは、とにかく読み込んだ場合にのみ実行可能になります。 –

関連する問題