ASP.NET MVC学前篇之Ninject的初步了解
1.介绍
废话几句。Ninject是一种轻量级的、基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,由于这样的IoC开源框架有非常多,本篇的主题仅仅有一个,就是让阅读过本篇幅的朋友逗知道IoC框架在项目中的作用,以及它的重要性。 这样做的目的是以便在以后的学习工作中选择自己中意的一个IoC框架来学习、使用,或者是自己去实现一个。好了,不废话了。
2.环境准备
1.新建个4.0Framework的一个控制台应用程序项目,名称为IoCDemo
2.在http://www.ninject.org/download网页中,下载Version 2.2版本号的Ninject程序集(之前版本号的不支持4.0库)。下载完毕解压后会看到如图1里的几个文件,在这里你仅仅须要关心名称为Ninject的文件,其他的忽略掉。
图1
3.在项目中新建个Lib文件夹,并把Ninject.dll、Ninject.pdb和Ninject.xml三个文件复制到文件文件夹下,而且加入引用到项目中。
如图2:
图2
环境准备工作做好了,能够安心的来看演示样例了。捎带一句Ninject.xml文件是程序集文件的凝视。只是都是英文的,对于姿势水平不高的屌丝来说这并不算是福利。当然也包含本人。(ps:谷歌翻译什么的非常好用)
3.初步认识、了解
从上一篇的文章中,能够了解到一个基础的IoC,这是站在容器对象的角度去考虑的。详细实现对象确实是能够动态的注入到容器对象中的。我们再看一下新的演示样例,并从中找到上一篇不足的地方,换个角度去看问题。
我们先定义了一个商品类,内容仅仅包括了商品的编号、名称和价格三个属性
代码3-1
1 /// <summary> 2 /// 货品 3 /// </summary> 4 public class Commodity 5 { 6 public string CommodityID { get; set; } 7 public string Name { get; set; } 8 public float Price { get; set; } 9 }
商品类型定义好了之后,我们再定义个货品的计价规范和它的一个基础实现
代码3-2
1 /// <summary> 2 /// 货品计价规范 3 /// </summary> 4 public interface IValuation 5 { 6 float CommodityValuation(params Commodity[] commodities); 7 } 8 9 /// <summary> 10 /// 货品计价规范实现一:商品价格合计 11 /// </summary> 12 public class CommoditySumValuation : IValuation 13 { 14 public float CommodityValuation(params Commodity[] commodities) 15 { 16 return commodities.Sum(commodity => commodity.Price); 17 } 18 }
这样看来架势和上一篇的同样,前段的确实是差点儿相同的,不要着急慢慢来看。再定义个容器对象,而且通过构造注入的方式来实现解耦,让容器对象和详细实现彻底的分离了。
代码3-3
1 /// <summary> 2 /// 购物车-容器对象 3 /// </summary> 4 public class ShoppingCart 5 { 6 private IValuation _Valuation; 7 public ShoppingCart(IValuation valuation) 8 { 9 _Valuation = valuation; 10 } 11 12 public float CommodityTotalPrice() 13 { 14 Commodity[] commodities = 15 { 16 new Commodity(){ CommodityID="A1", Price=14}, 17 new Commodity(){ CommodityID="A2", Price=76.5f}, 18 new Commodity(){ CommodityID="B2", Price=34.4f}, 19 new Commodity(){ CommodityID="C4", Price=23.1f} 20 }; 21 22 return _Valuation.CommodityValuation(commodities); 23 } 24 }
对于上面那句话的定义,站在不同角度定义结果是不同的。假设站在容器对象的角度来看,确实是实现了解耦。如图3
图3
从图中能够明白的看到ShoppingCart类型(容器)和CommoditySumValuation类型(详细实现)没有不论什么的关系,从而以达到解耦的目的,可是问题要结合到实际从client调用容器对象来看:
代码3-4
1 namespace IoCDemo 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 ShoppingCart shoppingCart = new ShoppingCart(new CommoditySumValuation()); 8 9 } 10 } 11 }
代码看到这里,想必大家都会头疼了。这整的叫什么事,饶了一圈还是耦合了。如图4
图4
这样的情况下IoC框架就能够派上用场了,本篇介绍的是Ninject。那当然是用Ninject了。依据前面的环境配置,
代码3-5
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 #region IoC框架功能 10 IKernel kernel = new StandardKernel(); 11 kernel.Bind<IValuation>().To<CommoditySumValuation>(); 12 IValuation valuation = kernel.Get<IValuation>(); 13 #endregion 14 15 ShoppingCart shoppingCart = new ShoppingCart(valuation); 16 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString()); 17 Console.ReadLine(); 18 } 19 } 20 }
这里是通过Ninject中的IKernel类型的Bind泛型方法来绑定IValuation类型,用To泛型方法中的类型表示是Bind方法中类型的实现,这样在kernel.Get<IValuation>()的时候是返回的CommoditySumValuation类型。这里对Ninject的使用并不多做介绍,而是側重的解释IoC的重要性及其作用。
这个时候的依赖结构例如以下图5
图5
这样可能看不出IoC的效果。我们再新增一些需求,而且更改CommoditySumValuation实现类,
代码3-6
1 /// <summary> 2 /// 计价折扣算法规范 3 /// </summary> 4 public interface IValuationDisCount 5 { 6 float ValuationDisCount(float listPrice); 7 } 8 9 /// <summary> 10 /// 计价折扣算法规范实现一:九折 走起 11 /// </summary> 12 public class DisCount : IValuationDisCount 13 { 14 15 public float ValuationDisCount(float listPrice) 16 { 17 return listPrice - (listPrice * 10 / 100); 18 } 19 }
加入了一个新需求规范和一个新的实现类,这样能够给商品总和来打折了。还需在CommoditySumValuation实现类中实现构造注入。改动代码例如以下:
代码3-7
1 /// <summary> 2 /// 货品计价规范实现一:商品价格合计 3 /// </summary> 4 public class CommoditySumValuation : IValuation 5 { 6 private IValuationDisCount valuationDisCount; 7 8 public CommoditySumValuation(IValuationDisCount valuationdiscount) 9 { 10 this.valuationDisCount = valuationdiscount; 11 } 12 13 public float CommodityValuation(params Commodity[] commodities) 14 { 15 return valuationDisCount.ValuationDisCount(commodities.Sum(commodity => commodity.Price)); 16 } 17 }
这个时候假设没有IoC框架的存在,看下client是怎么来调用的:
代码3-8
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 ShoppingCart shoppingCart = 10 new ShoppingCart(new CommoditySumValuation(new DisCount())); 11 12 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString()); 13 Console.ReadLine(); 14 } 15 } 16 }
执行一下相同也能得到结果。可是无论怎么的去抽象。在client调用都须要直接依赖于实现类,而不是高层次的抽象。
图7
从图中能够看出来这是多么的恐怖。又一次的改动下Main函数里的代码把IoC框架给使用起来。
代码3-9
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 #region IoC框架功能 10 IKernel kernel = new StandardKernel(); 11 kernel.Bind<IValuation>().To<CommoditySumValuation>(); 12 kernel.Bind<IValuationDisCount>().To<DisCount>(); 13 IValuation valuation = kernel.Get<IValuation>(); 14 #endregion 15 16 ShoppingCart shoppingCart = new ShoppingCart(valuation); 17 18 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString()); 19 Console.ReadLine(); 20 } 21 } 22 }
结果如图8:
图8
再来看一下依赖结构。
图9
Ninject框架会检查要返回的类型所依赖的全部类型,而且也会动态的注入到类型其中。
从图7和图9的对照中能够看出,仅仅有通过添加IoC框架来进行client和详细实现的解耦,没有这个中间层的添加还真的不好来实现消除耦合,而且IoC框架还能够进行动态配置。
本篇到这里结束了,对Ninject感兴趣的朋友请自行学习吧。
来源:https://www.cnblogs.com/zfyouxi/p/5231856.html