目錄
- 0.關于IOC
- 1.主要細節
- 2.具體示例
- 2.0 設計思路
- 2.1 實作IOCFac.cs
- 2.2 建立測試類和特性類
- 2.3 運作測試
- 參考及示例代碼下載下傳
shanzm-2020年3月17日 20:06:01
相關概念類知識,可以參考:
.NET中的控制反轉及AutoFac的簡單說明
- 使用反射程式集的方式擷取對象的類型
- 通過反射的方式擷取指定類型的的所有公共屬性
- 通過特性的方式篩選需要注入對象的類型
- 遞歸的方式為屬性注入依賴對象
- TODO:循環依賴、生命周期、執行個體作用域
- 首要,用什麼存儲對象,即什麼是對象容器?Dictionary類型做容器
- 其次,怎麼擷取對象的類型?反射程式集
- 再次,怎麼篩選對象類型?使用特性
- 最後,怎麼實作屬性注入?遞歸
public class IOCFactory
{
// IOC容器(建立的對象的容器)
// string key:對象類型名
// object value:對象執行個體
private Dictionary<string, object> iocDictionaries = new Dictionary<string, object>();
// IOC中對象類型的容器
// string key:類型名
// Type value:類型
private Dictionary<string, Type> iocTypeDictionaries = new Dictionary<string, Type>();
//加載程式集,将含有我們自定義的特性标簽的類的類型存儲到類型容器中
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;
}
}
建立兩個特性類:
// IOC容器類特性
// 标記了IOCServiceAttribute特性的類,被注冊到容器
[AttributeUsage(AttributeTargets.Class)]//表示該自定義的屬性隻能用于類之上
public class IOCServiceAttribute : Attribute
{
public IOCServiceAttribute()
{
}
}
// IOC依賴注入特性
// 标明IOCInjectAttribute特性的屬性,被注入
[AttributeUsage(AttributeTargets.Property)]//表示該自定義的屬性隻能用于類之上
public class IOCInjectAttribute : Attribute
{
public IOCInjectAttribute()
{
}
}
建立兩個含有自定義特性的類
[IOCService]
public class Student
{
[IOCInject]
public Teacher Teacher { set; get; }
public void Study()
{
Teacher.Teach();
Console.WriteLine($"學生:學習中……");
}
}
[IOCService]
public class Teacher
{
//[IOCInject]
//public Student _Student { set; get; }
public void Teach()
{
Console.WriteLine($"老師:教學中……");
}
}
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();
}
運作結果:
老師:教學中……
學生:學習中……
- 源碼下載下傳
作者:shanzm
歡迎交流,歡迎指教!