1

NinjectforDIを使用するASP.NETWebAPIアプリがあります。これは使用に最適です。私たちが検討していた改善の1つは、ある種の一意の識別子に基づいて、リクエストごとに機能の一部を交換する機能です。

例。2人の顧客が私たちの安らかなAPIを使用しています。どちらも同じ機能を取得します。3番目の顧客がAPIのスーパーバージョンの料金を支払いました。彼はリクエストを行い、スーパーdllをロードし、スーパー実装を標準インターフェースにバインドします。

基本的に私が見ているのは、Web APIとNinjectを使用して、DLLをロードし、リクエストごとにバインディングを交換できるかどうかです。

編集:

したがって、両方の答えは元の質問に対して正しいですが、私の意図は異なり、それを正しく説明しなかったのは私のせいです。私たちが持っているのは、誰もが利用できる機能の基本レイヤーです。これに加えて、この機能をオーバーライドするカスタムロジックを顧客ごとに実装する機能もあります。このロジックは、DLLとしてAzureBlobStorageに格納されます。

私たちがやりたいのは、顧客がリクエストを行ったときに、DLLを取得し、すべてのカスタムサービスをバインドしてから、これらの新しいバインディングを使用してリクエストを処理することです。

ホットスワップはこれを行うための最良の方法ではありませんか?私たちは十分に新しいので、これは私たちが検討しているものとは異なる方法で実装される一般的なものかもしれません。

ある程度までは、顧客ごとにカスタムバインディングを提供できるようにしたいと考えています。

編集2:

代替の実装があることがわかっている場合は、アイテムに条件付きバインディングを使用しますが、上記のシナリオでは、顧客情報を取得してdllをスキャンするまで、代替のバインディングがあるかどうかはわかりません。dllがあるかどうかさえわかりません。

プロジェクトでファイルを参照するのではなく、ファイルをドロップインできるように、この方法で実行したいと思います。

4

3 に答える 3

2

条件付きバインディングを使用します。

Bind<IMyService>().To<MyService>();
Bind<IMyService>().To<MyServiceForVIPs>().When(ctx => CurrentPrincipalIsVIP());
于 2013-01-09T16:31:17.607 に答える
2

リクエストごとにバインディングを交換できることを気にしません。しかし、できることは条件付きバインディングを使用することです。

例-デフォルトのバインディング:

protected override Ninject.IKernel CreateKernel()
{
    var kernel = new StandardKernel();

    kernel.Bind<IAuthorizationService>()
        .To<AuthorizationService>()
        .InRequestScope();

    kernel.Bind<IService>()
        .To<BasicService>();

    return kernel;
}

一部の基本ユーザーとVIPユーザーにIService(必要な場所に)注入します。BasicServiceExtraService

条件付きバインディングのさまざまな方法の詳細については、「Ninject-コンテキストバインディング」を参照してください。

編集

条件付きバインディングは引き続き使用できると思います。IKernel新しいdllからコンポーネントを登録する場所にを伝播するだけで済みます。たとえば、global.asaxdllモジュールを動的にロードするためにこれを持っています-アプリの起動時に実行されます。

モジュールのロード:

private void LoadAssemblies(IKernel kernel) {
    foreach (var fileName in Directory.GetFiles(Server.MapPath("~/App_Data"), "*.dll")) {
        Assembly loadedAssembly = Assembly.LoadFile(fileName);
        try {
            var moduleRegistrations = loadedAssembly.GetTypes()
                .Where(t => t.IsClass && t.IsAbstract == false && typeof (IMyModuleRegistration).IsAssignableFrom(t));

            foreach (var moduleRegType in moduleRegistrations ) {
                IMyModuleRegistration moduleReg = (IMyModuleRegistration) Activator.CreateInstance(moduleRegType);
                moduleReg.RegisterComponents(kernel);
            }
        }
        catch (ReflectionTypeLoadException exception) {
            ....
        }
    }
}

モジュール定義:

public class MyExtraModule : IMyModuleRegistration
{
     public void RegisterComponents(IKernel kernel)
     {
         kernel.Bind<IService>()
               .To<ExtraService>()
               .When(x => x.ParentContext
                           .Kernel.Get<IAuthorizationService>()
                           .IsVIPUser());
     }
}

ExtraServiceMyExtraModuleのdllがロードされている場合にのみ使用されます。

編集2

そのdllはどこかからダウンロードできます。ロードしてから、登録インターフェイスが実装されているかどうかをテストします。次に、その登録を呼び出して、完了です。私が見る唯一の問題は、参照をどこに保存するかですIKernel-おそらくいくつかの静的プロパティでHttpApplication十分でしょう。また、すでにロードされているdllを追跡する必要があります。

または、それ以降のバージョンでは、を拡張して、メソッドを使用してカーネルにロードするNinjectことを提案できます。このモジュールとカーネルを見てください-特に部分的に動的モジュールの読み込み-多分それはあなたが探しているものです。NinjectModulekernel.Load(..)

于 2013-01-09T16:35:22.723 に答える
1

私はあなたがコアのninjectモジュールを知っていると思います。すべてのコアninjectモジュールをカーネルにロードできます。特別なユーザーが到着したら、コアモジュールをアンロードし、ユーザー固有のモジュールをカーネルにロードできます。

より良いアプローチは、プラグイン領域に特別なカーネルを置くことです。したがって、実際には、プラグインごとのカーネルアプローチでは、必要なコアモジュールが読み込まれ、ユーザー固有のモジュールがあれば追加されます。ただし、パフォーマンスに影響を与える可能性があります。

于 2013-01-10T07:49:53.280 に答える