20

この質問は、特にNinjectとは関係ありません。これは一般的なコーディングの質問ですが、私がやろうとしていることよりも、Ninjectで問題を完全に処理するためのより良い方法があるかもしれない場合に備えて、ここに投稿します。

Global.asaxのインスタンスから、Ninject標準カーネルにグローバルにアクセスできるかどうかを知りたいです。

コードは次のとおりです。

public class MvcApplication : NinjectHttpApplication
{
    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();

        // MVC global registration, routing and filtering code goes here...
    }

    protected override IKernel CreateKernel()
    {
        return Container;
    }

    private static IKernel Container
    {
        get
        {
            IKernel kernel = new StandardKernel();
            kernel.Load(new ServiceModule(), new RepositoryModule());
            return kernel;
        }
    }
}

いくつかのクラスがある場合、たとえば、コントローラーとインターフェイスしないファサードクラスがあり、依存関係チェーンを開始したい場合、私の理解では、次を使用する必要があります。

_className = kernel.Get<IClassName>();

ただし、これを行うために私が知っている唯一の方法は、Ninject Standardカーネルの新しいインスタンスを作成することですが、正しく理解している場合は、基本的にNinjectカーネルの新しいインスタンスを作成することはお勧めできません。 2番目のカーネル。

それで、アプリケーションの開始時にGlobal.asaxでインスタンス化された既存のカーネルに、アプリケーションのどこからでもアクセスできますか、それとも完全にこれを行うためのより良い方法がありますか?

よろしく、

フレッドシャトー

4

4 に答える 4

2

Service Locator を機能させることができましたが、非常にうまく機能しているようです。要求が MVC コントローラー アクション メソッドを介してアプリケーションに入ると、Ninject は Ninject.Mvc.Extensions によって提供される通常の方法で機能します。コントローラー コンストラクターを介してインスタンス クラスを挿入します。リクエストが他の方法でアプリケーションに入ると、Service Locator を呼び出して、そのクラス コンストラクターにインスタンス クラスを提供します。

コードは次のとおりです。

まず、Microsoft.Practices.ServiceLocation への参照

そして、次の Ninject アダプター クラス。

public class NinjectServiceLocator : ServiceLocatorImplBase
{
    public IKernel Kernel { get; private set; }

    public NinjectServiceLocator(IKernel kernel)
    {
        Kernel = kernel;
    }

    protected override object DoGetInstance(Type serviceType, string key)
    {
        return Kernel.Get(serviceType, key);
    }

    protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
    {
        return Kernel.GetAll(serviceType);
    }
}

そしてGlobal.asaxで

public class MvcApplication : NinjectHttpApplication
{
    private static IKernel _kernel;


    protected override IKernel CreateKernel()
    {
        return Container;
    }

    private static IKernel Container
    {
        get
        {
            if (_kernel == null)
            {
                _kernel = new StandardKernel();
                _kernel.Load(new ServiceModule(), new RepositoryModule());

                ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(_kernel));
            }

            return _kernel;
        }
    }
}

このコードでは、既定のコントローラーに依存関係リゾルバーのフォールバックを提供する Ninject.Mvc.Extensions を使用する必要があることに注意してください。それ以外の場合は、カスタムの依存関係リゾルバーが必要になる場合があります。

これで私の懸念はすべて解決されたようです。インスタンス クラスを作成し、オブジェクト グラフ全体を解決し、必要な場所ならどこからでも動作します。そして、私が知る限り、アプリケーションごとに Ninject 標準カーネルは 1 つしかありません。

Service Locator パターンを使用することが嫌われていることはわかっていますが、複数の Ninject カーネルを使用することはさらに悪いことだと思います。

フレッド シャトー

于 2013-03-19T20:05:06.930 に答える
0

Ninject の Factory パターンの実装がもっと必要なようです。カーネルを Global.asax から、アプリケーションの残りの部分と対話できる Factory クラスに移行できます。

または、実行時に指定されたパラメータがインターフェイス バインディングを決定する場合は、サービスをラップできます。これは DI と ServiceLocater のハイブリッド セットアップですが、ServiceLocater はサービス レベルのインスタンス化でのみ発生し、他のすべてのレイヤーは通常 DI/IOC パターンでコーディングされます。

MyService : IService1
{
    public void DoSomething(MyCustomParameter parameter)
    {
        //Builds the Kernel using the supplied parameter
        //We've in our resolver bound IService1 To MyActualService
        var trueService = kernel.Get<IService1>();
        return trueService.DoSomething(parameter);
    }
}

MyActualService : IService1
{
    public void DoSomething()
    {
        //Do the Actual work
    }
}
于 2013-03-11T13:20:08.300 に答える