一、Ninject安装

Ninject是一个轻量级的开源的DI容器,可以通过Nuget直接安装:

二、Ninject的简单使用

模型代码:

//计算器接口
public interface ICalculator
{
decimal GetTotalValue(IEnumerable<Product> products);
}
//计算器实现类
public class LinqValueCalculator: IValueCalculator
{
public decimal GetTotalValue(IEnumerable<Product> products)
{
return products.Sum(p => p.Price);
}
}
//购物车
public class ShoppingCart
{
//计算器
private ICalculator calc;
public ShoppingCart(ICalculator calcParam)
{
calc = calcParam;
}
public IEnumerable<Product> Products { get; set; }
//算出商品价格
public decimal CalcProductTotal()
{
return calc.GetTotalValue(Products);
}
}

Ninject的简单使用:

    public class HomeController : Controller
{
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 flag",Category="soccer",Price=34.95M}};
// GET: Home public ActionResult Index()
{
//获取一个ninject内核对象,该对象负责解析依赖项和创建实例
IKernel ninjectKernel = new StandardKernel();
//注册服务,当我们需要ICalculator实例的时候,获取的是一个Calculator的实例
ninjectKernel.Bind<ICalculator>().To<Calculator>();
//获取实例
ICalculator calc= ninjectKernel.Get<ICalculator>(); //ICalculator calc = new Calculator();使用IoC容器就不用直接new了
ShoppingCart cart = new ShoppingCart(calc) { Products = products };
decimal total = cart.CalcProductTotal();
return View(total);
}
}

三、Ninject的封装使用

第一步:创建依赖项解析器

服务解析器用于注册服务, IDependencyResolver 接口在System.Mvc命名空间下

         public class NinjectResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectResolver()
{
kernel = new Ninject.StandardKernel();
AddBindings();
}
//获取服务实现类实例,没有合适的绑定是返回null
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
//当接口绑定多个服务实现类,可以使用getAll
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
} private void AddBindings()
{
kernel.Bind<ICalculator>().To<LinqValueCalculator>();
//...这里注册服务
}
}

第二步:注册依赖项解析器

创建了一个实现IDependencyResolver接口的实现是不够的,我们需要告诉MVC框架使用它

方法1:在MVC5中可以通过在APP_Start文件下的NinjectWebCommon.cs文件来注册依赖项解析器

private static void ResisterServices(IKernel kernel){
System.Web.Mvc.DependencyResolver.SetResolver(new NinjectResolver();
}

方法2:在global文件中添加注册

        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//在这里添加
System.Web.Mvc.DependencyResolver.SetResolver(new NinjectResolver());
}

第三步:重构Controller

     public class HomeController : Controller
{
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 flag",Category="soccer",Price=34.95M}};
ICalculator calc;//重构改动1
public HomeController(ICalculator calcParam)//重构改动2
{
calc = calcParam;
}
public ActionResult Index()
{
ShoppingCart cart = new ShoppingCart(calc) { Products = products };
decimal total = cart.CalcProductTotal();
return View(total);
}
}

四、Ninject的一些补充

Ninject中有一些很好用的功能,这里只列出几种常用的:

4.1 依赖项链

  一句话解释就是解析依赖项的依赖项,一个栗子,当计算器类(ICalculator的实现类)依赖于一个打折类,当创建HomeController时,要解析HomeController的依赖LinqValueCalculator,而LinqValueCalculator又依赖于打折类FlexibleDiscountHelper打折类,那么Ninject能在创建HomeController时将FlexibleDiscountHelper也解析出来,打折服务(IDiscountHelper)和一些打折类代码如下:

namespace EssentialTools.Models
{
//打折服务
public interface IDiscountHelper
{
decimal ApplyDiscount(decimal totalParm);
}
//默认打折类
public class DefaultDiscountHelper : IDiscountHelper
{
public decimal DiscountSize { get; set; }
public decimal ApplyDiscount(decimal totalParm)
{
return totalParm - DiscountSize / 100M * totalParm;
}
}
/// <summary>
/// 弹性打折类,100元以上折扣70%,少于100元折扣25%
/// </summary>
public class FlexibleDiscountHelper : IDiscountHelper
{
public decimal ApplyDiscount(decimal totalParm)
{
decimal discount = totalParm > ? : ;
return totalParm - discount / 100M * totalParm;
}
}
/// <summary>
/// 最小打折类,大于100元打9折,10~100元之间减5元,10元以下无优惠
/// </summary>
public class MinimunDiscountHelper : IDiscountHelper
{
public decimal ApplyDiscount(decimal totalParm)
{
if (totalParm < )
{
throw new ArgumentOutOfRangeException();
}
else if (totalParm > )
{
return totalParm * 0.9M;
}
else if ( <= totalParm && totalParm <= )
{
return totalParm - ;
}
else
{
return totalParm;
}
}
}
}

修改LinqValueCalculator为:

    //Linq计算器,用于计算商品总价
public class LinqValueCalculator:ICalculator
{
private IDiscountHelper discounter;//打折
public LinqValueCalculator(IDiscountHelper discountParm)//计算器依赖于打折类
{
discounter = discountParm;
}
public decimal ValueProducts(IEnumerable<Product> products){
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}
}

使用Ninject注册打折服务:

        private void AddBindings()
{
kernel.Bind<ICalculator>().To<LinqValueCalculator>();
kernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize",50M);//默认打折类打5折
kernel.Bind<IDiscountHelper>().To<MinimunDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();//给LinqValueCalculator注入打折服务时,解析FlexibleDiscountHelper
}

完成以上步骤后,不必更改HomeController中代码,运行程序即可,在程序创建HomeController的实例时,Ninject会将所有的依赖项都解析出来。

4.2  解析依赖项时传入属性值或构造器参数

//1.注入依赖项,给属性赋值。实例:注册默认打折类(DefaultDiscount)到打折服务(IDiscount),默认打折类的属性DiscountSize的值0.5(五折)
kernel.Bind<IDiscount>().To<DefaultDiscount>().WithPropertyValue("DiscountSize",0.5);
//2.注入依赖项时给构造器参数传值。还是上边的例子,如果DiscountSize不是DefaultDiscount的属性,而是构造函数的参数则使用下边代码进行赋值
kernel.Bind<IDiscount>().To<DefaultDiscount>().WithConstructorArgument("DiscountSize",0.5);

4.3   使用条件绑定

//当总价小于100时,选择的打折服务是默认打折类
kernel.Bind<IDiscount>().To<DefaultDiscount>().When(total<);
//当为LinqValueCalcutor计算器类注入打折服务时,打折服务选择Linqdiscount
kernel.Bind<IDiscount>().To<MinimunDiscountHelper>.WhenInjectedInto<LinqValueCalcutor>();

4.4   设置对象作用域

Niject中对象作用域的内容很多,这里只列出几种常用的方法

 kernel.Bind<IA>().To<A>().InTransientScope();//每个依赖项一个实例默认的
kernel.Bind<IA>().To<A>().InSingletonScope();//整个应用程序一个实例,单例
kernel.Bind<IA>().To<A>().InThreadScope();//每个线程一个实例
kernel.Bind<IA>().To<A>().InRequestScope();//每个请求一个实例

参考文献:

  本文参考的书籍是《精通ASP.NET MVC5》中文版,想了解更多内容的话可以参考这本经典的MVC教程。

IoC之Ninject的更多相关文章

  1. IOC框架Ninject实践总结

    原文地址:http://www.cnblogs.com/jeffwongishandsome/archive/2012/04/15/2450462.html IOC框架Ninject实践总结 一.控制 ...

  2. ASP.NET MVC IOC 之Ninject攻略

    ASP.NET MVC IOC 之Ninject攻略 一.为什么要使用Ninject? 很多其它类型的IOC容器过于依赖配置文件,老是配置,总感觉有点不爽,而且要使用assembly-qualifie ...

  3. 轻量级IoC框架Ninject.NET搭建

    说在之前的话 IOC的概念相信大家比较熟悉了,习惯性称之为依赖注入或控制反转,园子里对基于MVC平台IOC设计模式已经相当多了,但大家都只知道应该怎么应用一个IOC模式,比如Ninject, Unit ...

  4. 轻量级IOC容器:Ninject

    Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那 ...

  5. Ninject学习笔记<一>

    本文转载自永远的阿哲 如果给您带来不便请联系博主. Ninject是一款.Net平台下的开源依赖注入框架.按照官方说法,它快如闪电.超级轻量,且充分利用了.Net的最新语法,使用Lambda表达式代替 ...

  6. Ninject是一款.Net平台下的开源依赖注入框架

    Ninject是一款.Net平台下的开源依赖注入框架.按照官方说法,它快如闪电.超级轻量,且充分利用了.Net的最新语法,使用Lambda表达式代替Xml文件完成类型绑定.Ninject结构精巧,功能 ...

  7. IOC容器之Autofac

    讲到IOC容器,就必须提到DIP(依赖倒置原则). DIP是OOD(面向对象设计)的一个重要思想,在该原则上引申出了\IOC(控制反转)\DI(依赖注入)\IOC容器. 居然讲到IOC容器,当然我们要 ...

  8. webapi - 使用依赖注入

    本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity:由于快过年这段时间打算 ...

  9. DotNet 资源大全中文版(Awesome最新版)

    Awesome系列的.Net资源整理.awesome-dotnet是由quozd发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. 算法与数据结构 ...

随机推荐

  1. MYSQL ROW_FORMAT=Compact

    https://dev.mysql.com/doc/refman/5.6/en/innodb-row-format-antelope.html https://docs.oracle.com/cd/E ...

  2. [转载] 虚拟机下面安装windows+oracle ASM的过程

    转帖:https://www.2cto.com/database/201303/195261.html 最开始的时候 我找了一个挺好的教程 安装过 但是已经找不到了,先转载一下这个内容,后续再测试完善 ...

  3. HashMap, HashTable,HashSet,TreeMap 的时间复杂度

    hashSet,hashtable,hashMap 都是基于散列函数, 时间复杂度 O(1) 但是如果太差的话是O(n) TreeSet==>O(log(n))==> 基于树的搜索,只需要 ...

  4. prettier & codes format

    prettier & codes format https://prettier.io/playground/ https://github.com/collections/front-end ...

  5. 快速排序Qsort

    快速排序Qsort是所有学习算法和数据结构最基础的一个部分,也是考试题和面试的一个小重点. 快速排序的时间复杂度为O(N*lgN),而且常数因子很小. 对于随机数据,效率特别高: 对于构造的恶意数据, ...

  6. JSON:如果你愿意一层一层剥开我的心,你会发现...这里水很深——深入理解JSON

    我们先来看一个JS中常见的JS对象序列化成JSON字符串的问题,请问,以下JS对象通过JSON.stringify后的字符串是怎样的?先不要急着复制粘贴到控制台,先自己打开一个代码编辑器或者纸,写写看 ...

  7. BZOJ4764弹飞大爷——LCT

    题目描述 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值, ...

  8. LOJ6387 [THUPC2018] 绿绿与串串 【manacher】

    题目分析: 比较简单,先跑一边manacher,然后对于回文部分可以碰到末尾的一定满足条件,否则向后转移. 代码: #include<bits/stdc++.h> using namesp ...

  9. MT【21】任意基底下的距离公式

    解析: 评:$\theta=90^0$时就是正交基底下(即直角坐标系下)的距离公式.

  10. 02 自学Aruba之无线频段---ISM频段及UNII频段

    点击返回:自学Aruba之路 02 自学Aruba之无线频段---ISM频段及UNII频段 1. 无线频段-ISM频段 ISM频段即工业,科学和医用频段.一般来说世界各国均保留了一些无线频段,以用于工 ...