Dependency Injection 簡介
Dependency Injection 是一種物件改變耦合的一種設計概念,通常會跟 IOC(Inversion Of Control) 一起談
以下一個簡單的注入範例
範例
故事
父母今天要教育小孩科目,但一對父母並不是只會擁有一個小孩,可能會有多個。因此我們把小孩當作參數傳給教育小孩這個方法,使其變得有彈性。
方法中注入小孩其實就是 方法注入(Method Injection)
創建小孩的過程會注入一個姓名,這種注入方式就是 建構式注入(Constructor Injection)
透過物件設定值的方式,就是 屬性注入(Property Injection)
Struct
public interface IParent {
void TeachChild (IClild child, Subject string);
}
public class Parent: IParent {
public Parent () { }
public void TeachChild (IClild child, string subject ) {
Console.WriteLine($"Teach {child.GetName} about ${subject}")
}
}
public interface IChild {
string GetName ();
void SetAge(int age);
}
public class Child {
private string _childName;
private int _age;
public Child (string name) {
this._childName = name;
}
public string GetName() {
return this._childName;
}
public void SetAge(int age) {
this._age = age;
}
}
.NET 的特別之處
當我們知道 DI 之後,就要來細講 NET 的 DI 概念了
在 NET 的架構下,會建議改用框架預設的 IServiceCollection(IServiceProvider)
來取代手動 DI ,而透過 IServiceProvider 取出來的物件
概念如下圖
先將所有的 Service 註冊到資料提供中心,如果有其他物件需要就在從資料提供中心中取出來
這樣的好處是 Service 跟 其他物件的耦合性,會變成是跟資料提供中心耦合(詳細概念可參考前篇的AbstractClass比較Interface )
而在 Service 註冊的時候,會有三種特性,這三種特性會改變資料提供中心對外的時候,是否要產生新的物件(生命週期)給需求者,分別是
- Singleton: 在 APP 的生命週期中,只會存在一個實例,因此每次取回都是相同的記憶體位置
- Scoped: 在一個 Requeset 的過程中僅在第一次建立新的實例,第二次開始會取得與第一次同樣的實例
- Transient:每次要都取回一個新的實例
結語
透過 DI 的方式可以解決物件之間高耦合的問題,以利未來要做調整或抽象會更加簡單,而下一篇再來說明怎麼透過原生的 DI Pull 達成工廠模式
