概念:依賴注入與IOC模式類似工廠模式,是一種解決調用者和被調用者依賴耦合關系的模式;它解決了對象之間的依賴關系,使得對象只依賴IOC/DI容器,不再直接相互依賴,實現松耦合,然後在對象創建時,由IOC/DI容器將其依賴的對象注入其體內,故又稱依賴注入依賴注射模式,最大程度實現松耦合;
那麼什麼是依賴?如下代碼:
1 public class A{
2 private B b;
3 public A(B b){
4 this.b = b;
5 }
6 public void mymethod(){
7 b.m();
8 }
9 }
如下代碼表示A依賴B,因為A的方法行為mymehtod有一部分要依賴B的方法m實現。
容器信息:
1 /// <summary>
2 /// 依賴注入中的配置項(注入容器)
3 /// </summary>
4 public class MapItem : {
5
6 private Boolean _singleton = true;
7 private Dictionary<String, String> _maps = new Dictionary<String, String>();
8
9 /// <summary>
10 /// 容器創建對象的時候,是否以單例模式返回
11 /// </summary>
12 public Boolean Singleton {
13 get { return _singleton; }
14 set { _singleton = value; }
15 }
16
17 /// <summary>
18 /// 對象依賴注入關系的 map
19 /// </summary>
20 public Dictionary<String, String> Map {
21 get { return _maps; }
22 set { _maps = value; }
23 }
24
25 /// <summary>
26 /// 對象的 typeFullName
27 /// </summary>
28 public String Type { get; set; }
29
30 /// <summary>
31
32 /// 添加注入關系
33
34 /// </summary>
35
36 /// <param name="propertyName">屬性名稱</param>
37
38 /// <param name="item">注入容器</param>
39 internal void AddMap( String propertyName, MapItem item ) {
40 AddMap( propertyName, item.Name );
41 }
42
43 /// <summary>
44
45 /// 注入
46
47 /// </summary>
48
49 /// <param name="propertyName">屬性名稱</param>
50
51 /// <param name="injectBy">對象名稱</param>
52 internal void AddMap( String propertyName, String injectBy ) {
53 this.Map.Add( propertyName, injectBy );
54 }
55
56
57 private Object _obj;
58
59 /// <summary>
60
61 /// 目標對象
62
63 /// </summary>
64 [NotSave]
65 internal Object TargetObject {
66 get { return _obj; }
67 set { _obj = value; }
68 }
69
70 private Type _type;
71
72 /// <summary>
73
74 /// 目標類型
75
76 /// </summary>
77 [NotSave]
78 internal Type TargetType {
79 get {
80
81 if (_type != null) return _type;
82 if (TargetObject != null) return TargetObject.GetType();
83 return null;
84 }
85 set { _type = value; }
86 }
87
88 }
那麼看如何使用這個容器,我們一般外部需要調用的方法為:
/// <summary>
/// 創建一個經過Ioc處理的對象,結果不是單例。
/// 檢測是否需要注入。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Create<T>()
{
return (T)CreateObject(typeof(T), null);
}
/// <summary>
/// 創建一個經過Ioc處理的對象,結果不是單例。
/// 檢測是否需要注入。
/// </summary>
/// <param name="targetType"></param>
/// <param name="invokerName">如果是根據接口自動裝配,</param>
/// <returns></returns>
private static Object CreateObject(Type targetType, Object invoker)
{
if (targetType == null) return null;
if (targetType.IsInterface)
{
///接口
return CreateByInterface(targetType, invoker);
}
//這裡是用AOP實現對象的構建,可以參看上一篇博客
Object objTarget = AopContext.CreateObjectBySub(targetType);
//進行IOC注入
Inject(objTarget);
return objTarget;
}
/// <summary>
/// 根據容器配置(IOC),將依賴關系注入到已創建的對象中
/// </summary>
/// <param name="obj"></param>
public static void Inject(Object obj)
{
if (obj == null) return;
Type t = obj.GetType();
MapItem mapItem = getMapItemByType(t);
if (mapItem == null)
{
mapItem = new MapItem();
mapItem.TargetType = t;
mapItem.TargetObject = obj;
}
createInstanceAndInject(mapItem, obj);
}
/// <summary>
/// 根據類型查找DI容器
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private static MapItem getMapItemByType(Type t)
{
Dictionary<String, MapItem> resolvedMap = Instance.ResolvedMap;//當前對象的鍵值對容器
foreach (KeyValuePair<String, MapItem> entry in resolvedMap)
{
MapItem item = entry.Value;
if (t.FullName.Equals(item.Type)) return item;
}
return null;
}
/// <summary>
/// IOC注入:檢查對象的屬性,根據配置注入,如果沒有配置,則自動裝配
/// </summary>
/// <param name="mapItem"></param>
/// <returns></returns>
private static Object createInstanceAndInject(MapItem mapItem, Object objTarget)
{
Type targetType = mapItem.TargetType;
if (targetType.IsAbstract)
{
logger.Info("type is abstract=>" + targetType.FullName);
return null;
}
if (objTarget == null)
{
objTarget = rft.GetInstance(targetType);//根據反射創建對象
}
// 檢查所有屬性
PropertyInfo[] properties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in properties)
{
if (!p.CanRead) continue;
if (!p.CanWrite) continue;
// 不是接口的跳過
if (!p.PropertyType.IsInterface) continue;
// 對接口進行注入檢查
//-------------------------------------------------
// 如果有注入配置
Object mapValue = getMapValue(mapItem.Map, p);
if (mapValue != null)
{
p.SetValue(objTarget, mapValue, null);
}
// 如果沒有注入
else
{
Object propertyValue = p.GetValue(objTarget, null);
// 自動裝配
if (propertyValue == null)
{
logger.Info("property=>" + targetType.Name + "." + p.Name);
propertyValue = getAutoWiredValue(p.PropertyType);
if (propertyValue != null)
{
p.SetValue(objTarget, propertyValue, null);
}
else
{
logger.Info("property is null=>" + p.Name);
}
}
}
}
return objTarget;
}
容器檢查如果沒有則自動裝配
// IOC注入:檢查對象的屬性,根據配置注入,如果沒有配置,則自動裝配
private static Object createInstanceAndInject(MapItem mapItem)
{
return createInstanceAndInject(mapItem, null);
}
/// <summary>
/// 檢查映射關系中是否存在屬性信息
/// </summary>
/// <param name="maps"></param>
/// <param name="p"></param>
/// <returns></returns>
private static Object getMapValue(Dictionary<String, String> maps, PropertyInfo p)
{
if (maps == null || maps.Count == 0) return null;
foreach (KeyValuePair<String, String> entry in maps)
{
Object x = GetByName(entry.Value);
if (x != null) return x;
}
return null;
}
/// <summary>
/// 根據依賴注入的配置文件中的 name 獲取對象。根據配置屬性Singleton決定是否單例。
/// </summary>
/// <param name="objectName"></param>
/// <returns></returns>
public static Object GetByName(String objectName)
{
if (Instance.ResolvedMap.ContainsKey(objectName) == false) return null;
MapItem item = Instance.ResolvedMap[objectName];
if (item == null) return null;
if (item.Singleton)
return Instance.ObjectsByName[objectName];
else
return createInstanceAndInject(item);
}
根據接口自動綁定對象
// 根據接口,獲取自動綁定的值
private static Object getAutoWiredValue(Type interfaceType)
{
List<Type> typeList = GetTypeListByInterface(interfaceType);
if (typeList.Count == 0)
{
return null; // 返回null
}
else if (typeList.Count == 1)
{
return Create(typeList[0], interfaceType);
}
else
{
StringBuilder msg = new StringBuilder();
foreach (Type t in typeList)
{
msg.Append(t.FullName + ",");
}
throw new Exception(string.Format("有多個接口實現,接口={0},實現={1} 沒有明確指定,無法自動注入。", interfaceType.FullName, msg));
}
}
// 根據接口獲取實例
public static List<Type> GetTypeListByInterface(Type interfaceType)
{
List<Type> typeList = new List<Type>();
foreach (KeyValuePair<String, Type> kv in Instance.TypeList)
{
if (rft.IsInterface(kv.Value, interfaceType))
{
typeList.Add(kv.Value);
}
}
return typeList;
}