码迷,mamicode.com
首页 > 其他好文 > 详细

如何构建一个轻量级级的DI(依赖注入)

时间:2015-06-16 16:38:13      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:

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

 

如何构建一个轻量级级的DI(依赖注入)

标签:

原文地址:http://www.cnblogs.com/hui088/p/4580954.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!