依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,因此客户类只定义一个注入点。在程序运行过程当中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,而后将其注入到客户类中,保证客户类的正常运行。sql
图1数据库
如图1所示,数据库操做类DataManager中依赖的IDataBase的接口,而不是以来IDataBase的具体实现类,这样的好处是可让咱们的程序具备扩展性:不管咱们要使用SqlServer当咱们的数据库操做类仍是用Mysql,咱们须要改动的地方都不多。函数
咱们建立一个控制台程序,并按照图1中所标识的关系建立四个类。工具
public class DataManager { private IDataBase _database; public DataManager(IDataBase database) { this._database = database; } public void Add() { _database.Add(); } public void Delete() { _database.Delete(); } public void Update() { _database.Update(); } public void Select() { _database.Select(); } }
public interface IDataBase { string DbName { get; } void Select(); void Update(); void Delete(); void Add(); }
public class SqlServer : IDataBase { public string DbName { get { return "SqlServer"; } } public void Add() { Console.WriteLine("Add in " + DbName); } public void Delete() { Console.WriteLine("Delete in " + DbName); } public void Select() { Console.WriteLine("Select in " + DbName); } public void Update() { Console.WriteLine("Update in " + DbName); } }
public string DbName { get { return "Mysql"; } } public void Add() { Console.WriteLine("Add in " + DbName); } public void Delete() { Console.WriteLine("Delete in " + DbName); } public void Select() { Console.WriteLine("Select in " + DbName); } public void Update() { Console.WriteLine("Update in " + DbName); }
若是咱们要用Sqlserver做为数据库实现类的话,传统写法咱们要New Sqlserver,以下图:this
项目早期使用的是Sqlserver数据库没问题,后来BOSS突然要改为Mysql数据库,你内心面一想,没问题啊,无非就是把New后面的Sqlserver换成Mysql嘛,简单。因而你就开始改,越改越不对劲,已经你已经发现当前项目已经有好几十个地方用到New Sqlserver(),而剩余的数量每每仍是未知的。这个时候你就在想,有没有方法可让我只须要改一个地方其余地方不用动就能够呢?答案是确定的,目前这种方法实现有不少种,最简单的无非就是工厂模式。可是,今天,咱们不用工厂,咱们将使用Ninject来实现这种功能。spa
Ninject是一个IOC容器,用来解决程序中组件的耦合问题,它的目的在于作到最少配置。其余的的IOC工具过于依赖配置文件,须要使用assembly-qualified名称来进行定义,庸长且复杂经常由于打错字而破坏程序。这些是他的优势,也是为何要选择它。3d
打开Nuget程序包管理控制台输入“Install-Package Ninject”便可安装Ninject。code
咱们通常会在程序启动的入口来建立Ninject的对象负责类型的注册。server
1 static void Main(string[] args) 2 { 3 //实例化Ninject对象 4 IKernel Kerner = new StandardKernel(); 5 }
使用Ninject对象分两个步骤,第一步是把接口对象或者说被依赖的对象(IDataBase)绑定到Ninject中,而后在为其绑定对应的实例类型(若是要使用SqlServer则就绑定SqlServer)。对象
//实例化Ninject对象 IKernel Kerner = new StandardKernel(); //绑定对象 Kerner.Bind<IDataBase>().To<SqlServer>();
第二步则是经过Ninject的Get方法获取IDataBase的实现类
var Db = Kerner.Get<IDataBase>(); //因为上面IDataBase绑定的是SqlServer类型,因此这里获取的类型是SqlServer
上面的代码你们可能体会不到使用Ninject的好处,也没有体会到依赖注入的奥妙所在。依赖注入大体分为三类:接口注入,函数注入,属性注入。咱们来经过一个例子来演示属性注入。
咱们增长一个IShowDBInfo的接口类,其有一个Show方法。而后添加一个Show类实现IShowDBInfo接口:
public class Show1 : IShowDBInfo { public void Show() { Console.WriteLine(this.GetType().FullName); } }
咱们给DataManager添加一个IShowDBInfo属性并增长一个Show()方法:
public class DataManager { private IDataBase _database; private IShowDBInfo _showDbInfo; public DataManager(IDataBase database, IShowDBInfo ishowdbinfo) { this._database = database; _showDbInfo = ishowdbinfo; } //省略Add,Updata,Delete,Select方法 public void Show() { _showDbInfo.Show(); } }
在应用程序启动的时候注册IShow类和注册DataManager类并启动程序:
static void Main(string[] args) { //实例化Ninject对象 IKernel Kerner = new StandardKernel(); //绑定对象 Kerner.Bind<IDataBase>().To<SqlServer>(); Kerner.Bind<IShowDBInfo>().To<Show1>(); Kerner.Bind<DataManager>().ToSelf(); var dataManager=Kerner.Get<DataManager>(); dataManager.Show(); Console.Read(); }
从上代码以及运行结果来看,咱们只须要在向Ninject实例里面注册对象,而后在其余类中使用的时候咱们只须要定义接口就能够了,并不须要实例化对象。这样作的话可使咱们和其余层进行松耦合。