Ninject 是跟Unity 差不多的DI容器。Ninject 推荐零配置,快速使用。小中型项目,最适合。
通过nuget,安装Ninject.MVC。略。参考博客:Ninject依赖注入 WebForm中使用
场景模拟 项目下载地址:https://coding.net/u/chenxygx/p/CodeSave/git/tree/master/EssentialTools
定义一个计算产品的接口,IValueCalculator,往后都会围绕产品计算,来进行依赖注入。
namespace EssentialTools.Models { public interface IValueCalculator { decimal ValueProduct(IEnumerable<Product> products); } }
接下来定义产品实现,LinqValueCalculator
public class LinqValueCalculator : IValueCalculator { public decimal ValueProduct(IEnumerable<Product> products) { return products.Sum(p => p.Price); } }
Product,就是一个普通的实体类,就不贴了。
然后在控制器中,使用Ninject进行输出。
public class HomeController : Controller { private IValueCalculator calc; private Product[] products = { new Product { Name="Kayak",Category="Watersports",Price = 275M }, new Product { Name="Lifejacket",Category="Watersports",Price = 48.95M }, new Product { Name="Soccer ball",Category="Soccer",Price = 19.50M }, new Product { Name="Corner flagW",Category="Soccer",Price = 34.95M } }; // GET: Home public ActionResult Index() { IKernel kernel = new StandardKernel(); kernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); IValueCalculator calc = kernel.Get<IValueCalculator>(); return View(calc.ValueProduct(products)); } }
接下来,把Ninject跟MVC进行整合操作。首先需要添加一个Ninject依赖项解析器,NinjectDependencyResolver
public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver(IKernel kernelParam) { kernel = kernelParam; AddBindings(); } private void AddBindings() { kernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return kernel.GetAll(serviceType); } }
主要作用就是在页面加载之前,进行依赖注入。然后我们将解析器与MVC关联一下。在App_Start的NinjectWebCommon里面修改
private static void RegisterServices(IKernel kernel) { new NinjectDependencyResolver(kernel); }
这样,在MVC程序运行后,会首先进行依赖注入。然后就可以在需要的时候,控制反转出实例了。
接下来,实现构造器的控制反转
public class HomeController : Controller { private IValueCalculator calc; public HomeController(IValueCalculator calcParam) { calc = calcParam; } // GET: Home public ActionResult Index() { return View(calc.ValueProduct(products)); } }
控制反转会考察依赖项是否依赖其他类型,例如如果LinqValueCalculator,还有依赖项,则也会进行控制反转。
指定属性参数值
可以使用 WithPropertyValue 指定实例中属性的值。
kernel.Bind<IDiscountHelper>().To<DefuaultDicountHelper>().WithPropertyValue("DiscountSize", 50M)
会传递50M到DefuaultDicountHelper里面的 DiscountSize属性。
指定构造器参数
可以使用 WinthConstructorArugment方法指定构造器中参数的值。
kernel.Bind<IDiscountHelper>().To<DefuaultDicountHelper>().WithConstructorArgument("discountParam",50M); public DefuaultDicountHelper(decimal discountParam) { DiscountSize = discountParam; }
条件绑定
可以针对依赖注入设置对应条件,例如:要创建 LinqValueCalculator对象时,使用FlexibleDiscountHelper 作为 IDiscountHelper接口的实现。
kernel.Bind<IDiscountHelper>().To<FlexibleDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();
WhenInjectedInto<T>() 当要被注入的类是类型T时,进行绑定
WhenClassHas<T>() 当被注入的类以注解属性进行注释,而类型为T时,进行绑定
作用域
可以设置绑定的作用域
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>().InRequestScope();
InRequestScope() 创建一个单一实例,用于解析一个HTTP请求中各个对象的依赖项
InThreadScope() 创建一个单一实例,将其用于解析一个线程中各个对象的依赖项
InSingletonScope() 使其共享于整个应用程序