程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 如何構建一個輕量級級的DI(依賴注入),構建di注入

如何構建一個輕量級級的DI(依賴注入),構建di注入

編輯:C#入門知識

如何構建一個輕量級級的DI(依賴注入),構建di注入


概念:依賴注入與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;
        }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved