.NET實現一個簡單的IOC容器
阿新 • • 發佈:2020-03-17
[TOC]
shanzm-2020年3月17日 20:06:01
### 1.主要細節 * 使用反射程式集的方式獲取物件的型別 * 通過反射的方式獲取指定型別的的所有公共屬性 * 通過特性的方式篩選需要注入物件的型別 * 遞迴的方式為屬性注入依賴物件 * **TODO**:迴圈依賴、生命週期、例項作用域
### 2.具體示例 #### 2.0 依次考慮一下問題 * 首要,用什麼儲存物件,即什麼是物件容器?Dictionary型別做容器 * 其次,怎麼獲取物件的型別?反射程式集 * 再次,怎麼篩選物件型別?使用特性 * 最後,怎麼實現屬性注入?遞迴 #### 2.1 實現IOCFac.cs ```cs public class IOCFactory { // IOC容器(建立的物件的容器) // string key:物件型別名 // object value:物件例項 private Dictionary iocDictionaries = new Dictionary();
// IOC中物件型別的容器
// string key:型別名
// Type value:型別
private Dictionary iocTypeDictionaries = new Dictionary();
//載入程式集,將含有我們自定義的特性標籤的類的型別儲存到型別容器中
public void LoadAssmaly(string asmName)
{
Assembly assembly = Assembly.Load(asmName);
Type[] types = assembly.GetTypes();//注意這裡獲取的是程式集中的所有定義的型別
// 篩選出含有IOcServiceAttribute特性標籤的類,儲存其type型別
foreach (Type type in types)
{
IOCServiceAttribute iOCService = type.GetCustomAttribute(typeof(IOCServiceAttribute)) as IOCServiceAttribute;//獲取類上的自定義的特性標籤
if (iOCService != null)//如果是IOCServiceAttribute標註類,則把其型別存入型別容器中
{
iocTypeDictionaries.Add(type.Name, type);//最終其中的資料:{[Student, MyIOC.ClassLib.Student],[Teacher, MyIOC.ClassLib.Teacher]}
}
}
}
// ioc容器物件建立
public object GetObject(string typeName)
{
//根據引數取出指定的type
Type type = iocTypeDictionaries[typeName];
//建立type型別的物件
object objectValue = Activator.CreateInstance(type);
//獲取type型別物件的所有屬性
PropertyInfo[] propertyInfos = type.GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
//獲取類中屬性上的自定義IOCInjectAttribute特性標籤
IOCInjectAttribute iOCInject = (IOCInjectAttribute)propertyInfo.GetCustomAttribute(typeof(IOCInjectAttribute));
//如果該屬性是含有IOCInjectAttribute型別的特性,則為其也建立一個指定的例項(即注入依賴物件)
if (iOCInject != null)
{
//為objectValue的propertyInfo屬性賦值
//這裡使用了遞迴的方式建立一個指定型別的例項
propertyInfo.SetValue(objectValue, GetObject(propertyInfo.PropertyType.Name));
}
}
//將建立的物件儲存到容器中
iocDictionaries.Add(typeName, objectValue);
return objectValue;
}
}
```
#### 2.2 建立測試類和特性類
新建兩個特性類:
```cs
// IOC容器類特性
// 標記了IOCServiceAttribute特性的類,被註冊到容器
[AttributeUsage(AttributeTargets.Class)]//表示該自定義的屬性只能用於類之上
public class IOCServiceAttribute : Attribute
{
public IOCServiceAttribute()
{
}
}
```
```cs
// IOC依賴注入特性
// 標明IOCInjectAttribute特性的屬性,被注入
[AttributeUsage(AttributeTargets.Property)]//表示該自定義的屬性只能用於類之上
public class IOCInjectAttribute : Attribute
{
public IOCInjectAttribute()
{
}
}
```
新建兩個含有自定義特性的類
```cs
[IOCService]
public class Student
{
[IOCInject]
public Teacher Teacher { set; get; }
public void Study()
{
Teacher.Teach();
Console.WriteLine($"學生:學習中……");
}
}
```
```cs
[IOCService]
public class Teacher
{
//[IOCInject]
//public Student _Student { set; get; }
public void Teach()
{
Console.WriteLine($"老師:教學中……");
}
}
```
#### 2.3 執行測試
```cs
static void Main(string[] args)
{
IOCFactory iOCFactory = new IOCFactory();
iOCFactory.LoadAssmaly("MyIOC");
Student student = (Student)iOCFactory.GetObject("Student");
//student.Teacher = teacher;//不需要在為屬性賦值,IOCFactory實現了屬性的注入
student.Study();
Console.ReadKey();
}
```
執行結果:
> 老師:教學中……
> 學生:學習中……
### 參考及示例程式碼下載
* [某公開課]()
* [原始碼下載](https://github.com/shanzm/ASP.NET-MVC/tree/master/011%E6%89%8B%E5%86%99IOC
### 1.主要細節 * 使用反射程式集的方式獲取物件的型別 * 通過反射的方式獲取指定型別的的所有公共屬性 * 通過特性的方式篩選需要注入物件的型別 * 遞迴的方式為屬性注入依賴物件 * **TODO**:迴圈依賴、生命週期、例項作用域
### 2.具體示例 #### 2.0 依次考慮一下問題 * 首要,用什麼儲存物件,即什麼是物件容器?Dictionary型別做容器 * 其次,怎麼獲取物件的型別?反射程式集 * 再次,怎麼篩選物件型別?使用特性 * 最後,怎麼實現屬性注入?遞迴 #### 2.1 實現IOCFac.cs ```cs public class IOCFactory { // IOC容器(建立的物件的容器) // string key:物件型別名 // object value:物件例項 private Dictionary