詳解C# 依賴注入
前言
好久沒有寫微博了,因為前段時間由於家庭原因決定從工作了3年多的北京轉移到上海去。依賴注入在學習net core的時候也有寫過類似的東西,只是實踐的較少,結果來到上海新公司系統框架涉及到了這塊知識點,所以在瞭解完自己的專案之後決定做一些相關的總結。接下來就讓我們先來了解hewi依賴注入。
什麼是依賴注入
依賴注入,全稱是“依賴注入到容器”, 容器(IOC容器)是一個設計模式,它也是個物件,你把某個類(不管有多少依賴關係)放入這個容器中,可以“解析”出這個類的例項。所以依賴注入就是把有依賴關係的類放入容器(IOC容器)中,然後解析出這個類的例項。劃重點:依賴注入是為了實現控制反轉的一種設計模式。【現在知道gof之外還有其他的設計模式了吧。】
為什麼要用依賴注入
我們程式設計希望高內聚低耦合,所以解耦是很多理論的出發點,依賴注入控制反轉也是為了解耦。那麼冒昧問一下啊低耦合是什麼?我的理解就是:我們在程式設計過程中,我們不需要知道元件與類庫的內容只需知道他們提供的介面,呼叫介面就能實現功能,我們就說這種情況是低耦合。
在沒有接觸到依賴注入的時候,解耦的思路其實也就是gof設計模式和設計原則。我以前分享的很多文章牽涉到的封裝類庫都是基於面向介面的方式。舉個例子:
public interface IOrder { //Product 產品物件 decimal ValueProducts(params Product[] products); } public class Order : IOrder { public decimal ValueProducts(params Product[] products) { return products.Sum(p => p.Price*p.Number); } }
以上是在做商城經常寫的一個基類。比如我們以前商城中購物車下單就算其總價的方法呼叫的時候。
public class ShoppingCart { //計算購物車內商品總價錢 public decimal CalculateStockValue() { Product[] products = { new Product {Name = "龍牙2016新款",Number=2,ModelNo = 121,ColorID=65,SizeID=78,Price = 289.40},new Product {Name = "龍牙2017新款",Price =3800},}; IOrder order = new Order(); //計算商品總價錢 decimal totalValue = order.ValueProducts(products); return totalValue; } }
以上是我常用的方式來處理自己的業務需求的。這種面向介面的方式,如果我們要計算金額的方式改變了,比如我們尺寸32的金額打7折,那麼只需增加金額的類。改變介面例項化即可。程式碼就不敲了應該都懂吧(低耦合)。那麼我們可以看出ShoppingCart是依賴於介面與實現的對不對,那麼現在我們考慮一個問題,購物車雖然呼叫介面例項化,但是它也是要依賴於order的,那麼減少它的依賴性有沒有辦法——就是把他們完全分開。那麼這種問題的解決就用到了依賴注入了。劃重點:依賴注入就是減少對介面例項化物件的依賴。那麼怎麼來實現依賴注入呢?
構造注入的實現
通過類的建構函式
第一次看net core別人也是講的這種方式,下面看一下程式碼。設定一個服務類介面型別的資料成員,並以建構函式為注入點,這個建構函式接受一個具體的服務類例項為引數,並將它賦給服務類介面型別的資料成員。
public class ShoppingCart { IOrder order; //建構函式,引數為實現了IOrder 介面的類的例項 public ShoppingCart(IOrder _order) { order = _order; } //計算購物車內商品總價錢 public decimal CalculateStockValue() { Product[] products = { new Product {Name = "龍牙2016新款",Price =3800}}; //計算商品總價錢 decimal totalValue = order.ValueProducts(products); return totalValue; }
以上程式碼最秒的地方就是ShoppingCart與介面IOrder的實現order完全沒有關係,不需要了解他是怎麼實現的。這就是依賴注入。這種叫做構造注入。
在我們討論下一種注入的方式的時候,有個問題其實還沒有解決。“依賴是如何產生的?”把依賴當作建構函式引數來寫,儘管使用這可以手動提供這種依賴,但是當整個系統都依賴注入,那就意味著任何一個元件我們都需要知如道滿足每一部分的需求(服務定位器),是不是很頭大?那麼這時我們就要要引入一個概念的“容器”-----依賴注入容器。
protected override void RegisterBuilder(ContainerBuilderWrapper builder) { base.RegisterBuilder(builder); //注入倉儲 builder.RegisterType<Order>().As<IOrder>(); }
以上為mvc容器的一種實現。AS 後邊是服務類繼承的介面,其實我對它的理解就是:如果有人請求這種型別。我們就給他這個型別的物件。
屬性注入
其實依賴注入spring相關的資料應該有很多,所以很多知識點也是通過java那的理論借鑑過來的。屬性注入我確實看的net的書瞭解的。
如果需要使用到被依賴物件的某個屬性,在被依賴物件被建立之後,IoC容器會自動初始化該屬性
首先還是定一個介面
public interface Iorder { { //Product 產品物件 decimal ValueProducts(params Product[] products); } }
屬性注入如下:
public class ShoppingCart { private iordre _order; public iordre Order { get { return _order; } set { _order = value; } } public decimal ValueProducts(params Product[] products) { return Order.ValueProducts(products); } }
Setter注入
設定一個服務類介面型別的資料成員,並設定一個Set方法作為注入點,這個Set方法接受一個具體的服務類例項為引數,並將它賦給服務類介面型別的資料成員。其實這種是注入方式較為靈活使用者也較多。
//服務介面 internal interface IServiceClass { String ServiceInfo(); } //服務方法 internal class ServiceClassA : IServiceClass { public String ServiceInfo() { return "我是ServceClassA"; } } //服務方法 internal class ServiceClassB : IServiceClass { public String ServiceInfo() { return "我是ServceClassB"; } } //客戶類實現set internal class ClientClass { private IServiceClass _serviceImpl; public void Set_ServiceImpl(IServiceClass serviceImpl) { this._serviceImpl = serviceImpl; } public void ShowInfo() { Console.WriteLine(_serviceImpl.ServiceInfo()); } } //呼叫 class Program { static void Main(string[] args) { IServiceClass serviceA = new ServiceClassA(); IServiceClass serviceB = new ServiceClassB(); ClientClass client = new ClientClass(); client.Set_ServiceImpl(serviceA); client.ShowInfo(); client.Set_ServiceImpl(serviceB); client.ShowInfo(); } }
結束語
其實依賴注入可聊的有很多,net core的出現依賴注入是必不可少的一個知識點。後面可聊的比如依賴注入與反射,依賴注入與多型,依賴注入的框架。。。。。。。
好久不寫部落格,準備的也不夠充分。有興趣的小夥伴就去網上找去吧。
.net書的話:
《asp net mvc5 高階程式設計》《Dependency Injection in .NET 》(沒有中文)
java相關的書應該會多一些。有興趣的就一起學習一下吧。
以上就是詳解C# 依賴注入的詳細內容,更多關於c# 依賴注入的資料請關注我們其它相關文章!