概念:依赖注入与IOC模式类似工厂模式,是一种解决调用者和被调用者依赖耦合关系的模式;它解决了对象之间的依赖关系,使得对象只依赖IOC/DI容器,不再直接相互依赖,实现松耦合,然后在对象创建时,由IOC/DI容器将其依赖的对象注入其体内,故又称依赖注入依赖注射模式,最大程度实现松耦合;

那么什么是依赖?如下代码:

 public class A{
  private B b;
  public A(B b){
    this.b = b;
  }
  public void mymethod(){
    b.m();
  }
}

如下代码表示A依赖B,因为A的方法行为mymehtod有一部分要依赖B的方法m实现。

容器信息:

  /// <summary>
/// 依赖注入中的配置项(注入容器)
/// </summary>
public class MapItem : { private Boolean _singleton = true;
private Dictionary<String, String> _maps = new Dictionary<String, String>(); /// <summary>
/// 容器创建对象的时候,是否以单例模式返回
/// </summary>
public Boolean Singleton {
get { return _singleton; }
set { _singleton = value; }
} /// <summary>
/// 对象依赖注入关系的 map
/// </summary>
public Dictionary<String, String> Map {
get { return _maps; }
set { _maps = value; }
} /// <summary>
/// 对象的 typeFullName
/// </summary>
public String Type { get; set; } /// <summary> /// 添加注入关系 /// </summary> /// <param name="propertyName">属性名称</param> /// <param name="item">注入容器</param>
internal void AddMap( String propertyName, MapItem item ) {
AddMap( propertyName, item.Name );
} /// <summary> /// 注入 /// </summary> /// <param name="propertyName">属性名称</param> /// <param name="injectBy">对象名称</param>
internal void AddMap( String propertyName, String injectBy ) {
this.Map.Add( propertyName, injectBy );
} private Object _obj; /// <summary> /// 目标对象 /// </summary>
[NotSave]
internal Object TargetObject {
get { return _obj; }
set { _obj = value; }
} private Type _type; /// <summary> /// 目标类型 /// </summary>
[NotSave]
internal Type TargetType {
get { if (_type != null) return _type;
if (TargetObject != null) return TargetObject.GetType();
return null;
}
set { _type = value; }
} }

那么看如何使用这个容器,我们一般外部需要调用的方法为:

        /// <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 == ) 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 == )
{
return null; // 返回null
}
else if (typeList.Count == )
{
return Create(typeList[], 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(依赖注入)的更多相关文章

  1. Spring详解(三)------DI依赖注入

    上一篇博客我们主要讲解了IOC控制反转,也就是说IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建.初始化.销毁等工作交给spring容器来做.那么创建对象的时候,有可 ...

  2. 三大框架 之 Spring(IOC控制反转、DI依赖注入)

    目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...

  3. 手写Spring DI依赖注入,嘿,你的益达!

    目录 提前实例化单例Bean DI分析 DI的实现 构造参数依赖 一:定义分析 二:定义一个类BeanReference 三:BeanDefinition接口及其实现类 四:DefaultBeanFa ...

  4. .net 温故知新:【7】IOC控制反转,DI依赖注入

    IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图. 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时, ...

  5. 初识Spring框架实现IOC和DI(依赖注入)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的, IoC是 ...

  6. 谈谈php里的IOC控制反转,DI依赖注入

    理论 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明. 控制反转(In ...

  7. DI依赖注入/IOC控制反转

    DI依赖注入# 啥都不说,直接上代码 <?php class UserController { private $user; function __construct(UserModel $us ...

  8. IoC控制反转与DI依赖注入

    IoC控制反转与DI依赖注入 IoC: Inversion of Control IoC是一种模式.目的是达到程序的复用.下面的两篇论文是对IoC的权威解释: InversionOfControl h ...

  9. Spring:(二)DI依赖注入方式

    DI 依赖注入 DI(Dependency Injection)依赖注入,说简单一点就将类里面的属性在创建类的过程中给属性赋值,即将对象依赖属性(简单值,集合,对象)通过配置设值给该对象. 属性注入的 ...

随机推荐

  1. CALayer帧动画

    CALayer帧动画 _sunLayer = [[CALayer alloc]init]; _sunLayer.contents = (id)[UIImage imageNamed:@"su ...

  2. Android ViewPager使用方法小结

    android-support-v4.jar 是谷歌提供给我们的一个兼容低版本安卓设备的软件包,里面包囊了只有在 Android 3.0 以上可用的API.而 ViewPager 就是其中之一.利用它 ...

  3. 关于VM虚拟机在使用网络时与锐捷网络冲突的解决问题

    在使用NAT网络模式的时候,锐捷会因为冲突强制关闭NAT服务,导致虚拟机无法上网,解决的办法是让NAT服务一直保持启动,写一个bat脚本来一直检测服务是否在运行,并且进行启动操作. 当不需要用虚拟机的 ...

  4. 《java数据结构与算法》系列之“开篇”

    大学的时候学习数据结构,当时吧虽然没挂这门课,但是确实学的不咋地,再但是其实自己一直都觉得数据结构很重要,是基础,只有基础好了,后面的路才能走的更好. 懒惰真的是天下的罪恶之源.所以一直到现在都毕业了 ...

  5. 【转载】linux环境下大数据网站搬家

    这里说的大数据是指你的网站数据库大小至少超过了500M,当然只有50M的网站也同样可以用这样的方法来轻松安全的实现网站搬家,前提是你使用的是linux环境下的VPS或者独立服务器. 我们假设你的网站域 ...

  6. nodejs要远程连接另一个主机上的monogodb数据库服务器

    我的mongodb是装在linux下的. 首先,先添加用户 1.首先在mongodb服务器主机上进行terminal命令行,输入 mongo 2.输入 use admin 进入用户管理数据库 3.db ...

  7. jQuery插件的怎么写

    对于jQuery之前一直用,也看到过别人写的插件,直到最近才想着学习怎么写自己的jQuery插件,今天看了网上的一些资料,发现其实很简单的. 先看一个简单的jQuery插件的例子 <script ...

  8. Altova MapForce AMS/ACI/ISF自定义模板

    目前为止,我在百度上得到关于MapForce的信息少之又少,所以把自己的一些经验写下来,与大家分享. 如果要生成xml的话,就可以直接创建xml架构当作数据的目标文件. 以下是我做的AMS&A ...

  9. (转)C#开发微信门户及应用(1)--开始使用微信接口

    http://www.cnblogs.com/wuhuacong/p/3613826.html 微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习 ...

  10. js截取字符串测试

    function gget() { $.ajax({ type: "GET", url: "index", data: { U: '1234', P: '000 ...