概念:依赖注入与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. 14招搞定JavaScript调试

    14招搞定JavaScript调试 译者按: 很多时候,大家可能只是依靠console.log来调试JavaScript代码,这样做的局限性不言而喻,这篇博客将教你几招实用的调试技巧. 原文: The ...

  2. JS——事件详情(鼠标事件:clientX、clientY的用法)

    鼠标位置 >可视区位置:clientX.clientY 跟着鼠标移动的div案例 代码如下图:   这个案例,运用到前一篇文章中的event事件来处理.获取div的left和top值,当鼠标移动 ...

  3. ROS-URDF-建立模型

    前言:建立一个简单的urdf模型 详解请参看教程http://wiki.ros.org/urdf/Tutorials/Building%20a%20Visual%20Robot%20Model%20w ...

  4. 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree2

    试了一下先上再下的Treap方式,很高兴,代码变短了,但是,跑的变慢了!!!其实慢得不多,5%左右.而且这个版本的写法不容易写错..只要会一般可持久化Treap的人写着都不难...就是相对于(压行的) ...

  5. C#之MD5加密

    C#实现MD5加密 方法一 首先,先简单介绍一下MD5 MD5的全称是message-digest algorithm 5(信息-摘要算法,在90年代初由mit laboratory for comp ...

  6. classNum 表示学生的班号,例如“class05”。 有如下List  List list = new ArrayList();

    package a927; import java.util.ArrayList; import java.util.List; class Student { private String name ...

  7. phpmyadmin搭建

    phpadmin配置: 一.phpadmin安装及配置 1.解压phpadmin压缩包,并复制到 /usr/local/apache2/htdocs目录,重命名为dataManage 2.进入data ...

  8. Deutsch lernen (05)

    1. die Wahrheit, -en 真理:  - 真言,实情 Wir sollen die Wahrheit festhalten. 坚持:紧握 Im Wein liegt Wahrheit. ...

  9. (转)Bootstrap 之 Metronic 模板的学习之路 - (2)源码分析之 head 部分

    https://segmentfault.com/a/1190000006684122 下面,我们找个目录里面想对较小的文件来分析一下源码结构,我们可以看到,page_general_help.htm ...

  10. [iOS Reverse]logify日志追踪,锁定注入口-控制台查看

    前言 logify是theos的一个组件,路径是: /opt/theos/bin/logify.pl 我们还是以微信红包为例子,根据[iOS Hacking]运行时分析cycript得到的入口文件: ...