7

asp.netmvcテクノロジを使用して中規模のWebサイトを設計しています。すべてのビジネスロジックは、IServices(IDomainService、IUserService、IAuthService、ITrainingServiceなど)に編成されています。すべてのサービスがIRepositoriesを使用しています。Ninject 1.5を使用してコントローラーとのサービスを配線していますが、完全に機能しているようです。

これまでのところ、私がどのように扱うべきかわからない主題が1つあります。一部のサービスは(リクエストごとに)コンテキストを作成します。たとえば、IDomainServiceはIUserServiceに必要なDomainContext(リクエストごと)を作成します。ITrainingServiceは、許可されたユーザーのみがアクセスできるTrainingControllerでのみ使用され、ITrainingServiceは、誰がトレーニングを受けているかを知るためにUserContext(これもリクエストごと)を必要とします。

これは、IoCコンテナを使用した最初のプロジェクトです。それを解決するためのデザインパターンやコードスキーマはありますか?ActionFiltersを使用してコンテキストオブジェクトを埋めることができると思いますが、それらの存続期間を管理する方法と、IServicesがアクセスできるようにする場所を教えてください。(エレガントな方法で)

4

2 に答える 2

10

特にMVCアプリケーションでNinjectを使用しました。Ninjectを使用してこれを実現する方法は、依存関係の構成またはバインディングにあります。これを行うときは、オブジェクトの存続期間をどのように管理するかを指定します。Webアプリのほとんどの場合、質問で示したように、オブジェクトはリクエストごとになります。

あなたの質問で私が気づいたことの1つは、DomainContextがIDomainServiceオブジェクトによって作成されており、他のオブジェクトによって使用されていることです。ドメインサービスオブジェクトがDomainContextの一種のファクトリである場合、それほど問題はありません。これは、具体的なオブジェクトを提供し、依存関係を注入するようにNinjectを構成する方法の演習になります。

アプリケーションをどのように構成するかについての一般的なガイダンスは次のとおりです。インターフェイスとクラスについて完全に理解していないことに注意してください。

public class GlobalApplication : NinjectHttpApplication {
  protected override void RegisterRoutes(RouteCollection routes) {

    // Your normal route registration goes here ...

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",                                              
        "{controller}/{action}/{id}",                           
        new { controller = "Home", action = "Index", id = "" }  
    );

  }

  // This function is resposible for creating a Ninject kernel.  This is where 
  // the magic starts to happen.  
  protected override IKernel CreateKernel() {
    var modules = new IModule[] {
                                  new AutoWiringModule(),
                                  new AutoControllerModule(
                                        Assembly.GetExecutingAssembly()),
                                  new ServiceModule()
                                };

    return new StandardKernel(modules);
  }
}

Ninjectを機能させる最も簡単な方法は、NinjectHttpApplicationクラスからアプリケーションクラスを派生させることです。RegisterRoutesをオーバーライドメソッドに変更する必要があります。また、 CreateKernelと呼ばれるメソッドを実装する必要があります。CreateKernelメソッドは、それ自体がIoCコンテナであるNinjectカーネルを返す役割を果たします。

CreateKernelメソッドでは、Ninjectが提供するAutoControllerModuleがアセンブリをスキャンしてMVCコントローラークラスを探し、それらをコンテナーに登録します。これが意味するのは、これらのコントローラーへの依存関係は、Ninjectがアプリケーションのコントローラープロバイダーになったため、Ninjectによって注入できるようになったということです。ServiceModuleクラスは、すべてのサービスをNinjectに登録するために作成する必要があるクラスです。私はそれがこのように見えるだろうと推測しています:

internal class ServiceModule : StandardModule {
  public override void Load() {
    Bind<IDomainService>()
      .To<MyDomainService>()
      .Using<OnePerRequestBehavior>();

    Bind<DomainContext>()
      .ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
      .Using<OnePerRequestBehavior>();

    Bind<IService>()
      .To<MyServiceType>()
      .Using<OnePerRequestBehavior>();
  }
}

Ninjectは、構成のための非常に表現力豊かな流暢なインターフェイスを備えています。上記のように、各ステートメントは基本的に具象クラスをそれが実装するインターフェースに関連付けます。ステートメントの「Using」句は、オブジェクトがリクエストの存続期間中のみ存続することをNinjectカーネルに示します。したがって、たとえば、これは、同じ要求中にNinjectカーネルからIDomainServiceオブジェクトが要求されるたびに、同じオブジェクトが返されることを意味します。

あなたのコンテキストオブジェクトに関しては、私はあなたのドメインサービスがこれらのコンテキストを作成し、ある種のファクトリとして機能することを突き止めています。その点で、IDomainServiceからCurrentDomainContextというプロパティの値を取得することによって生成されるように、上記のインスタンスDomainContextクラスをバインドしました。それが上記のラムダが達成することです。Ninjectの「ToMethod」バインディングの良いところは、カーネルを使用してオブジェクトを解決できるNinjectアクティベーションコンテキストオブジェクトにアクセスできることです。これは、現在のドメインコンテキストを取得するために行うことです。

次のステップは、オブジェクトが依存関係を適切に受け入れることを確認することです。たとえば、ITrainingServiceTrainingControllerクラスでのみ使用されると言います。したがって、その場合、TrainingControllerにITrainingServiceパラメーターを受け入れるコンストラクターがあることを確認します。そのコンストラクターでは、 ITrainingServiceへの参照をメンバー変数に保存できます。のように:

public class TrainingController : Controller {
  private readonly ITrainingService trainingService;

  public TrainingController(ITrainingService trainingService) {
    this.trainingService = trainingService;
  }

  // ... rest of controller implementation ...
}

NinjectはすでにすべてのコントローラーをNinjectカーネルに登録しているため、このコントローラーが作成されてそのアクションが呼び出されると、trainingServiceメンバー変数を介してITrainingServiceへの参照が作成されます。

これがお役に立てば幸いです。IoCコンテナの使用は、非常に混乱する場合があります。注:Ninjectのドキュメントを確認することを強くお勧めします。これは、DI/IoCの概念だけでなくNinjectの非常によく書かれた入門書です。上記のAutoWiringModuleについての説明も省略しました。ただし、Nate Kohari(Ninjectの作成者)は、この機能について彼のブログに優れた記事を書いています。

幸運を!

于 2009-07-23T18:27:16.970 に答える
0

私があなたの問題を完全に理解しているかどうかは正確にはわかりませんが、このちょっとしたアドバイスがお役に立てば幸いです。

IoCコンテナーを使用する場合は、コンテナーにオブジェクトの存続期間の管理を処理させます。私は依存性注入にCastleWindsorとStructureMapのみを使用したので、Ninjectでこれを行う方法の具体的な例を示すことはできません。

Ninjectのドキュメントを見ると、オブジェクトの有効期間管理を指定するためのアクティベーション動作を確認したいと思います。

お役に立てれば。

于 2009-07-21T12:15:03.860 に答える