你的位置:首页 > ASP.net教程

[ASP.net教程]如何构建一个轻量级级的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     /// 对象依赖注入关系的 map19     /// </summary>20     public Dictionary<String, String> Map {21       get { return _maps; }22       set { _maps = value; }23     }24 25     /// <summary>26     /// 对象的 typeFullName27     /// </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;    }