2011-06-29 41 views
2

在抽象基控制器使用Ninject屬性我有以下代碼:物業注射沒有MVC3

public abstract class BaseController : Controller 
{ 
    public IUserService UserService { get; set; } 
} 

我所有的控制器從這個基本控制器繼承。我開始通過使用以下代碼在Ninject中配置它:

kernel.Bind<BaseController>() 
     .ToSelf() 
     .WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService))); 

這沒有奏效。我認爲這是因爲BaseController是一個抽象類(請確認我的假設)。所以我繼續修改配置爲:

kernel.Bind<HomeController>() 
     .ToSelf() 
     .WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService))); 

這是行不通的。小的缺點是我現在必須以相同的方式配置每個控制器。

因爲我也有DependencyResolver建立在我的ASP.NET MVC 3項目我還可以刪除上述Ninject配置和修改我的基本控制器看起來像:

public IUserService UserService 
    { 
     get 
     { 
      return DependencyResolver.Current.GetService<IUserService>(); 
     } 
    } 

有沒有用流利的任何好處配置,而不是使用DependencyResolver方法?這個比那個好嗎?哪種方法會被認爲是更好的做法?

值得一提的是,我不想在我的基礎控制器中做構造函數注入。

+1

一直沒有這個問題已經被問和[使用Ninject 2房產注射液基本控制器(在回答http://stackoverflow.com/questions/3154240/property-injection-in-base-controller-using-ninject -2 /),儘管形式稍有不同。 – mrydengren

+0

這個問題涉及到MVC 3中的DependencyResolver,而前一個沒有。問題是,哪種方法更好,而不是如何做到這一點。 – Thomas

+0

MVC3/DependencyResolver完全沒有變化 –

回答

2

MVC中的一種更好的做法是使用構造函數注入來覆蓋屬性注入。你爲什麼選擇這樣的選擇?

使用你指出,在構造所有的依賴關係是必要的爲班級做它的工作構造器注入。

地產注入意味着依賴是可選或有當地的默認實現,所以一切都將工作,即使你不自己提供必要的實現。

你應該真的知道你在做什麼使用屬性注入或者你沒有其他選擇,所以更安全的方法是依賴構造函數注入。

現在我會給你我的觀點。其他人可能有其他意見。

DependencyResolver在MVC 3「方便」的服務定位出臺,但對我來說這是一個普通的服務定位器這對我來說也是一種反模式http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx。我不使用它,因爲我不喜歡它,使用它沒有任何好處。 我更喜歡像以前一樣使用我的控制器工廠,並通過構造函數傳遞依賴關係。

更多IDependencyResolver與一些IoC容器有問題(我不知道Ninject是否屬於這種情況)。你可以在這裏閱讀更多:http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html

0

有很多方法來皮膚他們說的貓。您可以使用基於約定的約束與.WithPropertyValue().OnActivaction()(如here所述)。

public class ControllerModule : NinjectModule 
{ 
    public override void Load() 
    { 
     // Get all controller types derived from the base controller. 
     IEnumerable<Type> controllerTypes = // ... 
     foreach (var controllerType in controllerTypes) 
     { 
      Bind(controllerType).ToSelf().InRequestScope() 
       .WithPropertyValue(...); 
     } 
    } 
} 

描述hereIControllerActivator界面的自定義實現您可以創建IInjectionHeuristic界面的自定義實現。

public class CustomNinjectControllerActivator : IControllerActivator 
{ 
    private readonly IKernel kernel; 

    public CustomNinjectControllerActivator(IKernel kernel) 
    { 
     this.kernel = kernel; 
    } 

    public IController Create(RequestContext context, Type controllerType) 
    { 
     var baseController = kernel.TryGet(controllerType) as BaseController; 
     if (baseController == null) 
     { 
      return null; 
     } 

     baseController.UserService = kernel.Get<IUserService>(); 
     return baseController; 
    } 
} 

哎呀,你甚至可以使用服務定位器模式,如果你願意使用它。

public IUserService UserService 
{ 
    get { return DependencyResolver.Current.GetService<IUserService>(); } 
} 

您應該選擇哪一種解決方案最容易實現,測試和維護,當然也會提供所需的行爲。

+0

是否有一種方法被認爲更「正確」?我可以實現其中的任何一個,它會工作並做它需要做的事情,但哪一個纔是最正確的方法? – Thomas

+0

我會說,正確的是提供最少的努力。在這種情況下,最有可能的是自定義控制器激活器或服務定位器(依賴關係定位器)。但正如@Remo Gloor指出的那樣,您可能希望完全避開這種架構。 – mrydengren

2

如果你需要在每個控制器相同的依賴則似乎有什麼不對您的設計。很可能你正在處理基本控制器中的一些交叉問題。在這種情況下,進行財產注射只是治療症狀而不是治癒疾病。這應該由一個方面(例如過濾器或攔截器)來處理,以便您不必使用不屬於那裏的某些東西來污染控制器。