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类型(具体实现)没有任何的关系,从而以达到解耦的目的,但是问题要结合到实际从客户端调用容器对象来看:

代码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框架的存在,看下客户端是怎么来调用的:

代码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 }

运行一下同样也能得到结果,但是不管怎么的去抽象,在客户端调用都需要直接依赖于实现类,而不是高层次的抽象,

图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框架来进行客户端和具体实现的解耦,没有这个中间层的加入还真的不好来实现消除耦合,并且IoC框架还可以进行动态配置。
本篇到这里结束了,对Ninject感兴趣的朋友请自行学习吧。

作者:金源

出处:http://www.cnblogs.com/jin-yuan/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

Ninject学习笔记<三>的更多相关文章

  1. Ninject学习笔记<四>

    前言 前段时间看Mvc最佳实践时,认识了一个轻量级的IOC框架:Ninject.通过google搜索发现它是一个开源项目,最新源代码地址是:http://github.com/enkari/ninje ...

  2. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  3. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  4. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  5. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  8. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  9. python3.4学习笔记(四) 3.x和2.x的区别,持续更新

    python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...

  10. Go语言学习笔记四: 运算符

    Go语言学习笔记四: 运算符 这章知识好无聊呀,本来想跨过去,但没准有初学者要学,还是写写吧. 运算符种类 与你预期的一样,Go的特点就是啥都有,爱用哪个用哪个,所以市面上的运算符基本都有. 算术运算 ...

随机推荐

  1. Can we say objects have attributes, states and behaviors?

    15down votefavorite 3 I was reading through Oracle's introduction to OOP concepts and I came across ...

  2. knowledgeroot 配置

    首先下载 KnowledgeRoot 的安装包,就是一个压缩文件,解压缩后放到 WebRoot 下面 在浏览器中打开网站,自动提示进行安装,安装的过程很简单,安装结束后即可以使用. 安装包创建的数据库 ...

  3. [Unity3D]UI方案及制作细节(NGUI/EZGUI/原生UI系统)

    转载请留下本文原始链接,谢谢.本文会不定期更新维护,最近更新于2013.09.17.   http://blog.sina.com.cn/s/blog_5b6cb9500101bplv.html   ...

  4. openerp所用QWEB2的调试笔记

    [1] 调式qweb模板时, 可以脱离openerp环境 阅读一下openerp目录 qweb目录中的几个html文件,可以作为起步 在浏览器下, 可以这样运行这些文件 http://127.0.0. ...

  5. DB2解锁

    1.登录数据库 db2 connect to 数据库名字 user 用户名 using 密码 2.进入db2top db2top -d 数据库名 进入到如下界面:  3.按下shift+u(图中U-L ...

  6. flask-Migrate模块

    功能 flask-migrate是flask的一个扩展模块,主要是扩展数据库表结构的. 官方文档:http://flask-migrate.readthedocs.io/en/latest/ 安装 p ...

  7. 由于删除DBF文件报错 —— ORA-01033: ORACLE initialization or shutdown in progress

    由于移动或删除DBF文件报错:ORA-01033: ORACLE initialization or shutdown in progress   原因:一般该类故障通常是由于移动文件而影响了数据库日 ...

  8. applicationContext.xml 文件头报错Referenced file contains errors

    问题如下:原先运行正常的项目,突然在applicationContext.xml 文件头报错 内容:Referenced file contains errors (http://www.spring ...

  9. MATLAB 的通用命令

    MATLAB 的通用命令 1.MATLAB 的标点符号及其特殊功能. 2.MATLAB 的键盘按键及其特殊功能. ↑或者Ctrl+p:调用上一次的命令 ↓或者Ctrl+n:调用下一行的命令 ←或者Ct ...

  10. lucene 范围搜索表达式(range expression)

    实际测试 lucene范围符号,大于等于或小于等于符号[],大于或小于符号{}   newIntRange或newLongRange一样     代码:           // test lucen ...