依賴注入(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實例裏面註冊對象,而後在其餘類中使用的時候咱們只須要定義接口就能夠了,並不須要實例化對象。這樣作的話可使咱們和其餘層進行鬆耦合。