2009-05-24 21 views
5

私はC#クラスのlibaryをいくつか書きますが、私はクラスに依存性注入を提供するためにNinjectを使いたいと思います。クラスlibaryがロードされるたびに実行されるコード(メソッド)をクラスlibaryが宣言することは可能ですか? Ninjectのバインディングを定義するには、これが必要です。アセンブリ後に実行されるC#メソッドがロードされる

答えて

1

私は過去9ヶ月間にかなりの量のNinjectを使用しています。あなたがする必要があるようなサウンドは、バインディングを登録するためにあなたのライブラリにあるモジュールをNinjectカーネルに「ロード」することです。

Ninject 1.xまたは2.0ベータ版を使用しているかどうかはわかりません。 2つのバージョンは、概念が少し異なりますが、概念は同じです。私はこの議論のためにバージョン1.xに固執するでしょう。私が知らない他の情報は、あなたのメインプログラムがNinjectカーネルをインスタンス化していて、あなたのライブラリが単にそのカーネルにバインディングを追加している場合、またはあなた自身のライブラリにカーネルとバインディングが含まれている場合です。私はあなたのライブラリ内のバインディングをメインアセンブリの既存のNinjectカーネルに追加する必要があると仮定しています。最後に、このライブラリを動的にロードしており、メインプログラムに静的にリンクされていないことを前提にします。

最初に行うことは、すべてのバインディングを登録するライブラリにninjectモジュールを定義することです。すでにこれを行っているかもしれませんが、言及する価値はあります。例:

public class MyLibraryModule : StandardModule { 
    public override void Load() { 
    Bind<IMyService>() 
     .To<ServiceImpl>(); 
    // ... more bindings ... 
    } 
} 

バインドがNinjectモジュールに含まれているので、アセンブリをロードするときに簡単に登録できます。アセンブリをロードしたら、StandardModuleから派生したすべての型をスキャンできます。これらのタイプがあれば、それらをカーネルにロードすることができます。

// Somewhere, you define the kernel... 
var kernel = new StandardKernel(); 

// ... then elsewhere, load your library and load the modules in it ... 

var myLib = Assembly.Load("MyLibrary"); 
var stdModuleTypes = myLib 
         .GetExportedTypes() 
         .Where(t => typeof(StandardModule).IsAssignableFrom(t)); 


foreach (Type type in stdModuleTypes) { 
    kernel.Load((StandardModule)Activator.CreateInstance(type)); 
} 

上記のコードをさらに一般化して、複数のライブラリを読み込んで複数のタイプを登録することができます。また、前述のように、Ninject 2には、この種の機能が組み込まれています。実際には、ディレクトリのスキャン、アセンブリのロード、モジュールの登録が可能です。とてもかっこいい。

シナリオが私が概説したものと少し異なる場合、同様の原則が適用される可能性があります。

6

C++のDllMainに相当するものを探しているようですね。 C#でこれを行う方法はありません。

あなたのシナリオに関する詳細とDllMainスタイル関数で実行するコードが必要な理由を教えてください。

タイプに静的コンストラクタを定義しても、この問題は解決されません。静的型コンストラクタは、型自体が使用される前に実行されることが保証されています。静的コンストラクタを定義し、その型にアクセスしないDll内の他のコードを使用することができます。コンストラクタは決して実行されません。

-1

私の知る限り、答えは ではありません。あなたのクラスライブラリにIoCコンテナを設定したいと思うのですが、そのような場合はそうするのは良い考えではありません。あなたのバインディングをどのような依存関係注入の使用ですか?私たちは依存性注入を使用して実行時に依存性を注入し、異なるシナリオで異なるオブジェクトを注入することができます.IoCコンテナを構成する最も良い場所はアプリケーションの起動です(IoCコンテナはアプリケーションのバックボーンのようなものです:))しかし、アプリケーションを起動する責任があるブートストラップに配置する必要があります。単純なアプリケーションでは、Mainメソッドにすることができます。

+0

クラスライブラリでバインディングを定義したい状況がたくさんあります。異なるライブラリ内の同じサービスの異なる実装を潜在的に持つことができます。どちらも、サービスが使用されるコンテキストに基づいて、同じアプリケーション内で同時に関連する可能性があります。 Ninject(他のIoCと同じように)は、コンテキストバインディングを定義する機能を提供しているため、いくつかの提供されたコンテキストに基づいて異なるコンクリートサービスを起動することができます。 –

0

クライアントコードを制御できますか?はいの場合、アセンブリをロードするときに魔法を行おうとするのではなく、バインディングを行うRegistryのような単一クラスを実装し、IRegistryインターフェイスを実装します。ロード中にアセンブリ内でIRegistryの実装を探し、必要なメソッドを起動できます。

また、あなたのクラスの属性を持つことができます。これらの属性の

[Component(Implements=typeof(IMyDependency)] 

外観と、クライアント側のコンテナにそれらをロードします。

または、この種の状況のライブラリであるMEFをご覧ください。

1

AppDomain.AssemblyLoadイベントを試しましたか?アセンブリがロードされた後で起動します。

AppDomain.CurrentDomain.AssemblyLoad += (s, e) => 
{ 
    Assembly justLoaded = e.LoadedAssembly; 
    // ... etc. 
}; 
関連する問題