2013-08-30 38 views
1

主要問題:如何發現在其他層中使用Ninject.MVC3配置的依賴項?使用Ninject.MVC3發現其他層模塊中的依賴項

背景:

我在我的ASP.NET MVC4項目之一使用Ninject.MVC3。

我以前使用過ServiceLocator,但是對於Ninject來說是新的。新的增強功能對Ninject的設置和配置非常簡單。

新的Ninject.MVC3 Nuget包,在您的Web項目的App_Start文件夾中添加一個「NinjectWebCommon」類,這就是我們配置所有依賴關係的地方。這個類是靜態的,除了啓動和停止靜態方法外,不會暴露任何外部的東西,它返回void。

爲了使用它,您可以在其「RegisterServices」方法中配置相關性,例如,

private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<IDataContext>().To<MyDataContext>().WithConstructorArgument("connectionString", "name=MyDataContext"); 

     kernel.Bind<IRoleService>() 
     .To<RoleService>() 
     .WithConstructorArgument("dbContext", context => context.Kernel.Get<IDataContext>()); 
    } 

在業務層,我們可以使用任何配置的服務,例如,

public class RoleService : IRoleService 
{ 
    private readonly IDataContext _dbContext; 

    public RoleService(IDataContext dbContext) 
    { 
     _dbContext = dbContext; 
    } 
} 

現在假設我們要添加一個新的依賴說ILogger到RoleService這個類。目前我已經如何做到這一點是這樣的:

public class RoleService : IRoleService 
{ 
    private readonly IDataContext _dbContext; 
    private ILogger _logger; 

    public RoleService(IDataContext dbContext, ILogger logger) 
    { 
     _dbContext = dbContext; 
     _logger = logger; 
    } 
} 

我想知道這是允許模塊發現依賴唯一的(或理想或標準)的方式?

隨着ServiceLocator我會做這樣的:

public class RoleService : IRoleService 
    { 
     private readonly IDataContext _dbContext; 
     private readonly Lazy<ILogger> _logger;   

     public RoleService(IDataContext dbContext) 
     { 
      _dbContext = dbContext; 
      _logger = Locator.Current.GetInstanceLazy<ILogger>(); 
     } 
    } 

我試圖尋找Ninject左右,但大多發現構造基於注射。

基於構造函數的方法的問題很明顯,因爲您添加更多的依賴關係構造函數參數列表增長。我知道,SRP進入圖片:)但你知道< 3依賴是正常的。每個類都需要DbContext,每個類都需要一個記錄器,並且如果你碰巧有一個單獨的審計功能,那麼這個功能就比第三個功能要多。

什麼是基於屬性的注入處理。我剛剛嘗試過,我添加了如下屬性:

[Inject] 
    public IRoleWrapper RoleWrapper { get; set; } 

存在於業務層的RoleService類中。該屬性未初始化並設置爲null。我應該怎麼做才能讓Ninject初始化它,請注意,ninject初始化是在MVC web項目中完成的。

總結我的問題是:

  1. 有什麼更好的辦法了這兩個構造Vs的物業注射w.r.t.的Ninject MVC3包?

  2. 有沒有其他方法可以在我的業務層類中發現依賴關係,就像我可以使用ServiceLocator一樣?

  3. 屬性注入在上述情況下應該如何工作?

在此先感謝。

回答

2

1)我更喜歡構造函數因爲它讓我更好地瞭解,我習慣了
2)你應該建立在層的底部,包括UI項目應使用該對象
3的每個組件的StandardKernel objcet )你必須通過ninject實例化。 Ninject將填充構造函數參數,並搜索屬性注入的類型。
實施例:

public interface IBusinessClass { 
    int DoWork(); 
    } 

    public class BusinessClass : IBusinessClass 
    { 
    public int DoWork() 
    { 
     return 10; 
    } 
    } 
    public interface IBusinessClass2 
    { 
    int DoWork2(); 
    } 

    public class BusinessClass2 : IBusinessClass2 
    { 
    public int DoWork2() 
    { 
     return 20; 
    } 
    } 
    public class Consumer 
    { 
    public IBusinessClass2 BusinessClass2 { get; set; } 

    [Inject] 
    public IBusinessClass BusinessClass { get; set; } 

    public Consumer(IBusinessClass2 businessClass2) 
    { 
     BusinessClass2 = businessClass2; 
    } 
    } 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     IKernel kernel = new StandardKernel(); 
     kernel.Bind<IBusinessClass>() 
      .To<BusinessClass>(); 
     kernel.Bind<IBusinessClass2>() 
      .To<BusinessClass2>(); 

     Consumer c = kernel.Get<Consumer>(); 
     Console.WriteLine(c.BusinessClass.DoWork()); 
     Console.WriteLine(c.BusinessClass2.DoWork2()); 
     Console.ReadKey(); 
    } 
    } 

UPDATE:
關於MVC模塊。它會在添加到項目中時爲您生成NinjectWebCommon.cs。
它有一個Create()方法中:

private static IKernel CreateKernel() 
{ 
    var kernel = new StandardKernel(); 
    kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

    RegisterServices(kernel); 
    return kernel; 
} 

修改此方法N,使用新的內核,但內核從基庫:

private static IKernel CreateKernel() 
{ 
    var kernel = // kernel from base library 
    kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

    RegisterServices(kernel); 
    return kernel; 
} 
+0

感謝彼得。考慮到我們有多層拱門,我們應該創建一個單獨的庫項目,在該項目中我們將添加Ninject並使用依賴關係進行配置。在啓動或啓動期間的Web項目中,我們將初始化此新庫。我是否正確?現在試試吧... – SBirthare

+0

你可以在其他庫中使用webactivator:[assembly:WebActivatorEx.PreApplicationStartMethod(typeof(className),「parameterlessStaticMethodOfThatClass」)] –

+0

創建一個單獨的庫項目,將Ninject安裝到其中。配置了一個依賴項。 Web項目有一個對這個程序集的引用,對調試開始方法正在調用。但是現在有一個參數的控制器ctor沒有被調用。 「沒有爲此對象定義的無參數構造函數。」我把[注入]放在控制器中,但同樣的問題。我想我必須做一些額外的事情才能讓Ninject在項目之間分享,將會探索。任何建議? – SBirthare

相關問題