一、为什么要使用依赖注入框架

  依赖注入框架也叫IoC容器。它的作用使类与类之间解耦

  我们看看为什么要用依赖注入框架,举个几个梨子:

  1,高度耦合的类

  

有一个Order类,Order类是用于订单操作的,DataAccess使用的sqlserver的方式查询订单。看看代码:

public class Order
{
private DataAccess dataAccess = new DataAccess();
public string QueryOrder()
{
return dataAccess.QueryOrder();
}
} public class DataAccess
{
public string QueryOrder()
{
return "sqlserver查询Order";
}
}

  看到这两个类(Order,DataAccess),它们出现了高度耦合。如果产品汪突然狂犬病大发让我们换成MySql方式查询,我们不得不修改Order类的private DataAccess data = new DataAccess() 和DataAccess的QueryOrder方法。这里违反了开放封闭原则(对扩展开放,对修改关闭),当然一个项目不只只有订单(Order)操作,还有购物车、产品等等操作,那改动起来将会是一场噩梦。

  2,使用依赖倒转原则来改进

  依赖倒转原则口诀:高层次模块不应该依赖于低层次模块,要依赖抽象,不要依赖具体。

  口诀听着很绕口,其实理解起来并不难,看下面的类图,Order相当于是高层模块,SqlServerData和MySqlData相当于底层模块,高层模块依赖于接口,所以可以随时更换底层模块

  

  我们现在把DataAccess抽象为接口,使SqlServerData和MySqlData实现IDataAccess

    public class Order
{
private IDataAccess dataAccess = new MySqlData();
public string QueryOrder()
{
return dataAccess.QueryOrder();
}
} public interface IDataAccess
{
string QueryOrder();
} public class SqlServerData : IDataAccess
{
public string QueryOrder()
{
return "sqlserver查询Order";
}
} public class MySqlData : IDataAccess
{
public string QueryOrder()
{
return "MySql查询Order";
}
}

  现在我们高层模块依赖于接口,如果产品汪再叫我们换Oracle数据库,我们就可以再添加一个OracleData类,然后实现IDataAccess接口,然后在Order类中的private IDataAccess dataAccess = new MySqlData()改为private IDataAccess dataAccess = new OracleData()。虽然改动的地方减少了,但是我们还是修改了类。可是我们并不希望修改类,就可以更换数据访问,这就需要解耦,需要用到Ioc容器,我们的Ninject终于该出场了,出场费还不低哦!

二、实战Ninject

  

1,使用注册机制

  首先安装一个Ninject的Dll,我们用NuGet安装。

  ①反键项目引用,选中管理NuGet程序包

  

  ②搜索Ninject,点击安装

  

  ③代码实现(只实现Order类操作,Product类操作与Order类一致)

  IDataAccess:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace RegisterNinject
{
public interface IDataAccess
{
string QueryOrder();
}
}

  MySqlDataOrder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace RegisterNinject
{
public class MySqlDataOrder : IDataAccess
{
public string QueryOrder()
{
return "MySql查询Order";
}
}
}

  SqlServerDataOrder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace RegisterNinject
{
public class SqlServerDataOrder : IDataAccess
{
public string QueryOrder()
{
return "sqlserver查询Order";
}
}
}

  Register:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject; //引入命名空间
namespace RegisterNinject
{
public class Register
{
private StandardKernel _kernel = new StandardKernel();
// 在这里注册
public Register()
{
_kernel.Bind<IDataAccess>().To<MySqlDataOrder>();
//_kernel.Bind<IDataAccess>().To<SqlServerDataOrder>();
//_kernel.Bind<IDataProduct>().To<SqlServerDataProduct>();
} //获取
public TInterface Get<TInterface>()
{
return _kernel.Get<TInterface>();
} public void Dispose()
{
_kernel.Dispose();
}
}
}

  Order:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace RegisterNinject
{
public class Order
{
private Register reg = new Register();
public string QueryOrder()
{
return reg.Get<IDataAccess>().QueryOrder();
} }
}

 这样,妈妈再也不用担心我换数据库了。如果产品汪再让我们换回sqlserver数据库[神经病](小插曲:换数据库是举的例子,Ioc容器的意义是让类与类之间解耦的,不是换数据库用的!),我们只需要在Register类中的构造函数中修改注册即可。

  有人说,"你还是修改了类呀!"。Register类的定位不一样,他是一个公共类,专门提供注册机制的。如果不去要修改类,就能完成换数据库,那就要引入新的概念———热插拔技术。

  

2,使用Xml文件(热插拔)

  现在我们用xml文件的方式,动态的更换接口。我们需要建一个xml文件。把他放在项目中。

  Register.xml

<?xml version="1.0" encoding="utf-8" ?>
<module name="register">
<bind service="XmlNinject.IDataAccess,XmlNinject" to="XmlNinject.SqlServerDataOrder,XmlNinject"/>
</module>

 注意:module元素,name属性,bind元素,service属性,to属性为规定的元素属性,不能写成别的。格式也要正确。

  然后更改下Register:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject; //引入命名空间
using Ninject.Extensions.Xml;//引入命名空间
namespace XmlNinject
{
public class Register
{
private StandardKernel _kernel = new StandardKernel(); // 以后这里就不用更改这里了,只需要该xml文件就可以了
public Register()
{
var settings = new NinjectSettings() { LoadExtensions = false };
_kernel = new StandardKernel(settings, new XmlExtensionModule());
_kernel.Load("Xml/Register.xml");
} //获取
public TInterface Get<TInterface>()
{
return _kernel.Get<TInterface>();
} public void Dispose()
{
_kernel.Dispose();
}
}
}

  以后要更换接口,直接更改xml文件就可以了。

   源码下载http://pan.baidu.com/s/1sjJXVrv  

Ninject的更多相关文章

  1. Ninject学习(一) - Dependency Injection By Hand

    大体上是把官网上的翻译下而已. http://www.ninject.90iogjkdcrorg/wiki.html Dependency Injection By Hand So what's Ni ...

  2. ASP.NET MVC学前篇之Ninject的初步了解

    ASP.NET MVC学前篇之Ninject的初步了解 1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开 ...

  3. [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject

    本人博客已转移至:http://www.exblr.com/liam  为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离( ...

  4. [ASP.NET MVC 小牛之路]05 - 使用 Ninject

    在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...

  5. 依赖注入(DI)和Ninject,Ninject

    我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,I ...

  6. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)

    前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...

  7. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)

    前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法 ...

  8. Ninject使用介绍

    #region 第二种写法 /// <summary> /// using(IKernel tKernel=new StandardKernel(new PeoKernelServer() ...

  9. 使用Ninject进行DI(依赖注入)

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

  10. Ninject之旅之十一:Ninject动态工厂(附程序下载)

    摘要 如果我们已经知道了一个类所有的依赖项,在我们只需要依赖项的一个实例的场景中,在类的构造函数中引入一系列的依赖项是容易的.但是有些情况,我们需要在一个类里创建依赖项的多个实例,这时候Ninject ...

随机推荐

  1. bzoj 1044 [HAOI2008]木棍分割(二分+贪心,DP+优化)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1044 [题意] n根木棍拼到一起,最多可以切m刀,问切成后最大段的最小值及其方案数. ...

  2. 20155223 2016-2017-2 《Java程序设计》第7周学习总结

    20155223 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 第十二章 Lambdo表达式下,任何参数的类型必须标明清楚:如果有目标类型的话,在编译程序可 ...

  3. centos7.2 安装 nginx

    Centos 7 源码编译安装 Nginx 1.13 原文地址:https://renwole.com/archives/39 1.先决条件: centos7.2 64位,安装配置nginx前必须安装 ...

  4. C# XML序列化和反序列化

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  5. python入门 20141102-1405

    那Python有哪些缺点呢? 第一个缺点就是运行速度慢,和C程序相比非常慢, 第二个缺点就是代码不能加密. Python是解释型的 不是编译型的 Python解释器-CPython 命令行: 只需要在 ...

  6. ip_local_deliver && ip_local_deliver_finish

    当ip包收上来,查路由,发现是发往本地的数据包时,会调用ip_local_deliver函数: ip_local_deliver中对ip分片进行重组,经过LOCAL_IN钩子点,然后调用ip_loca ...

  7. go语言版本变化

    The Go Project     Go is an open source project developed by a team at Google and many contributors  ...

  8. scala tuple中的syntactic sugar

    List[Tuple2[String, Int]] // Base List[(String, Int)] // Syntactic sugar List[Tuple3[String, Float, ...

  9. 使用qshell备份七牛云存储文件

    qshell是利用七牛文档上公开的API实现的一个方便开发者测试和使用七牛API服务的命令行工具.我们可以利用它来将七牛云上存储的文件备份到本地. 它提供Mac OSX, Linux, Windows ...

  10. Java模拟按键

    JDK自带了Robot类,此类用于为测试自动化.自运行演示程序和其他需要控制鼠标和键盘的应用程序生成本机系统输入事件.Robot 的主要目的是便于 Java 平台实现自动测试. 详情可查看jdk1.6 ...