开发ASP.NET MVC项目时,往往涉及大量的层与层之间的依赖关系,如UI层对BLL层的依赖、BLL层对DAL层的依赖。但是层与层之间的直接依赖会导致层与层之间的耦合度过高,这样一来,一旦某一层的某个类需要修改,很有可能会带动依赖这个类的所有类都需要修改,比如BLL层中的有一个UserInfoService类,对DAL层的UserInfoDal直接依赖,则UserInfoDal的修改,会直接导致UserInfoService的修改,而对于一个大型的项目,同一个数据访问类很可能被很多业务逻辑类调用,因此在直接依赖的作用下,需要修改所有依赖了该数据访问类的代码,这样一来,一方面工作量巨大,消耗的人工成本会很高,另一方面在巨大的工作量下,人工修改难免不出现一些疏漏,导致系统故障,无法运行。因此一般的项目都需要解决层与层之间的直接依赖的问题,而依赖注入就是基于“高内聚低耦合”思想诞生出来的技术。
本文主要介绍在ASP.NET MVC5 的环境下使用Ninject进行属性依赖注入的方法步骤和注意点。
步骤:
1.安装Ninject
在Visual Studio中的MVC项目中“管理NuGet包”中搜索“Ninject”,主要安装 Ninject、Ninject.MVC5,Ninject.Web.Common.WebHost 这三个库。
2.创建Ninject依赖注入容器类
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
/// <summary>
/// 添加绑定
/// </summary>
private void AddBindings()
{
//添加方式如下:左边括号里的是接口,后边括号里的实现接口的类
kernel.Bind<IUserService>().To<UserService>();
}
}
3.在global.asax文件中注入该容器
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//注册Ninject容器
DependencyResolver.SetResolver(new NinjectDependencyResolver());
}
}
4.在调用的文件类中添加属性注入
public class UserController : BaseController
{
[Ninject.Inject]
public IUserService UserService { get; set; }
}
如此一来,便可以将实例注入到引用的接口中了,后期如果想要修改注入的实例,则只需要改变Ninject容器类中的添加绑定方法中的实例,即可修改所有的引用的实例,节约了大量的人工修改成本。
5.注:该方法不支持基类属性的注入
//BaseController为基类,此时采用同样的方法,UserService 属性不会被注入实例
public class BaseController : Controller
{[Ninject.Inject]
public IMenuService MenuService { get; set; }
}
此时,可采用构造函数的方法将派生类中注入的属性传给基类
public class UserController : BaseController
{
[Ninject.Inject]
public IUserService UserService { get; set; }
[Ninject.Inject]
public new IMenuService MenuService { get; set; }
public TransactionController()
{
base.MenuService = this.MenuService;
}
}
或者采用构造函数注入的方法进行注入,由于本文讲的是属性注入,因此构造函数的注入方法就不赘述了,或者基类中的属性也可以不使用依赖注入的方法,对下一层进行直接依赖也是可以的,毕竟基类只有一个,依赖的类不多的情况下,修改的工作量也不大,直接依赖对系统的影响也很小。