2012-02-13 7 views
2

再利用可能な繰り返しコードがたくさんあることに気付いたので、コントローラ用にカスタムActionResultを作成しています。私が午前問題は、私は私のExtendedViewResultオブジェクトを作成するかどうかはわかりませんということですオブジェクトの作成時の依存性注入

public ExtendedViewResult<T> : ActionResult 
{ 
     protected T Model { get; set; } 
     protected IModelExtender<T> Extender { get; set; } 

     public ExtendedActionResult(T model, IModelExtender<T> extender) 
     { 
      this.Model = model; 
      this.Extender = extender; 
     } 
} 

public class BaseController : Controller 
{ 
    public ExtendedViewResult<T> ExtendedView<T>(T model) 
    { 
     // I need to create the result here, but how? 
     var result = new ExtendedViewResult<T>(model, ???????); 

     return result; 
    } 
} 

:それは次のようになります。インターフェイスは一般的なので、私は適切なオブジェクトを取得するためにDependency Injectionを使いたいですが、オブジェクトを自分で構築しているので、それをどうやって行うのか分かりません。私は場合

Ninject.Web.Mvc.Bootstrapper.Kernel is obsolete. Do not use Ninject as Service Locator.

:私はNinjectとNinject.MVC3を使用していますが、デフォルトNugetパッケージは私のためのブートストラップクラスを作成し、私はBootstrapper.Kernelプロパティにアクセスするとき、私は次の警告を得る

カーネルに直接アクセスすることは想定されていませんが、適切な具象クラスを得るためにコードを変更するにはどうしたらいいですか?

EDIT
ここにninjectブートストラップコードがあります。私は追加唯一の方法は、あなたがあなたのオブジェクトが他のオブジェクトを作成したいいつでも抽象工場を使用する必要があり

public static class NinjectMVC3 
{ 
    private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 

    /// <summary> 
    /// Starts the application 
    /// </summary> 
    public static void Start() 
    { 
     DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule)); 
     DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule)); 
     bootstrapper.Initialize(CreateKernel); 
    } 

    /// <summary> 
    /// Stops the application. 
    /// </summary> 
    public static void Stop() 
    { 
     bootstrapper.ShutDown(); 
    } 

    // I ADDED THIS CODE, EVERYTHING ELSE IS AUTO-GENERATED 
    // BY THE NUGET PACKAGE 
    public static T GetInstance<T>() 
    { 
     return bootstrapper.Kernel.Get<T>(); 
    } 

    /// <summary> 
    /// Creates the kernel that will manage your application. 
    /// </summary> 
    /// <returns>The created kernel.</returns> 
    private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     RegisterServices(kernel); 
     return kernel; 
    } 

    /// <summary> 
    /// Load your modules or register your services here! 
    /// </summary> 
    /// <param name="kernel">The kernel.</param> 
    private static void RegisterServices(IKernel kernel) 
    { 
    }   
} 

答えて

1

申し訳ありませんが実際のコードでは乾燥しています - 私は多くのninjectを使用していませんが、他のDIコンテナにはこの解決策があり、ninjectにもこの構造があります。

問題は、オブジェクト自体を構築していることです。 DIコンテナを実際に使用し、IoCに従っているときはいつでも、キーワードnewが赤い旗になるはずです。コンテナをサービスロケータとして使うのは黄色です。

新しいオブジェクトが必要なので、私たちはどのようにして「新」を取り除きますか?答えは、BaseControllerExtendedViewResultを作成できるファクトリに依存させることです。私のコンテナであるAutofacでは、Func<ExtendedViewResult>が注入されているほど簡単です。 Ninjectに同じものがないと私は驚くだろう。実際、そうであるように見えます - this ninject wiki pageはこれを指しますblog post on Ninject.Extensions.Factory

だから、コントローラのコードは次のようになります意味:あなたのベースクラスで作成を行うあなたが本当に一般的な方法を持っているしたい場合は

public class ConcreteController : BaseController 
{ 
    private Func<Foo,ExtendedViewResult<Foo>> _factory; 
    public BaseController(Func<Foo,ExtendedViewResult<Foo>> factory) 
    { 
     _factory = factory; 
    } 

    public ExtendedViewResult<Foo> Method(Foo model) 
    {    
     var result = _factory(model);  
     return result; 
    } 
} 

、あなたはおそらく、明示的に移動する必要があります上にリンクされたブログポストからの工場のインターフェイスルート。しかし、このスタイル・コードでは、ほとんどの場合、これを必要とせず、コントローラーは必要な依存関係を明示的に宣言します。

+0

これをコンクリートコントローラに渡す際の問題は、すべてが異なるモデルを持つ10種類のアクションメソッドを持つことができることです。これを行うには、私のコントローラに10種類のFunc依存関係を渡す必要がありますが、これは最良の選択肢のようには見えません。 – Dismissile

+0

@Dismissileその場合は、自分で工場を作ることをお勧めします。私はninjectがオープンジェネリックに基づいて工場を自動作成することはできないと考えています。コンストラクタパラメータはそれを難し​​くしています。できることが分かっている場合は、質問を更新し、この回答を編集したり、自分の質問に答えてください。結果を見たいと思っています。私のコンテナはAutoFacです。これを達成するためにいくつかの登録ソースウィザードが必要になると思います。 –

+0

@自分自身の工場に関しては、IResolutionRootに依存して、その上で.Getを呼び出すことができます。単純なケースでは、単にBaseControllerのIResolutionRootに依存することができます。これはServiceLocatorを使用していますが、あなたは自分自身を見つけるよりも、依存関係としてロケータを要求しています。 –