2013-08-30 39 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

相关问题