其他层中的依赖项发现';s模块使用Ninject.MVC3
本文关键字:模块 MVC3 Ninject 依赖 发现 其他 | 更新日期: 2023-09-27 18:29:34
主要问题:如何在其他层中发现使用Ninject.MVC3配置的依赖项?
背景:
我在我的一个ASP.NET MVC4项目中使用了Ninject.MVC3。
我以前使用过ServiceLocator,但对Ninject来说是个新手。通过新的增强功能,设置和配置Ninject非常简单。
新的Ninject.MVC3 Nuget包将一个"NinjectWebCommon
"类添加到您的web项目的App_Start文件夹中,这就是我们配置所有依赖项的地方。这个类是静态的,除了返回void的Start和Stop静态方法之外,不公开任何外部内容。
为了使用它,您可以在其"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;
}
}
现在假设我们想向这个类RoleService
添加一个新的依赖项,比如ILogger。目前我必须这样做:
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项目中完成的。
总结一下我的问题是:
从这两个Constructor Vs Property注入w.r.t.Ninject MVC3包中,有什么更好的方法?
有没有其他方法可以像使用ServiceLocator一样在业务层类中发现依赖关系?
在上述情况下,属性注入应该如何工作?
提前谢谢。
1)我更喜欢构造函数,因为它能给我更好的概述,我已经习惯了
2) 您应该在层的底部创建StandardKernel对象,包括UI项目在内的每个组件都应该使用该对象
3) 您必须通过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();
}
}
更新:
关于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;
}