概念:依赖注入与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. 《疯狂Python讲义》重要笔记--变量

    一个Python解释器 接下来的旅程——你需要下载好Python,Python解释器通常放在 /usr/local/bin/python3.7 ; 在Unix系统的bash中输入 where pyth ...

  2. go的常量与变量

    一.常量 1.1 定义 常量使用关键字const 定义,用于存储不会变化的数据 定义方法 const identifier [type] = value package main // 常量定义 co ...

  3. [hihocoder][Offer收割]编程练习赛60

    hohahola #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #in ...

  4. KVO的使用及底层实现

    1.概念 KVO(Key-Value-Observer)也就是观察者模式,是苹果提供的一套事件通知机制.允许对象监听另一个对象特定属性的改变,并在改变时接收到事件,一般继承自NSObject的对象都默 ...

  5. HangFire的定时任务和Quartz.NET总结(三)Quartz 配置

    在一个Net Core需求中,需要在每天的凌晨三点去抓取两个电商仓库的剩余的每个料号的数量来写会自己的表中, 用到了HangFire的定时任务 这篇文章讲的很详细记录下   文章2  这篇更简单 Qu ...

  6. C#获取窗口大小和位置坐标 GetWindowRect用法

    [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetWi ...

  7. 【原创】redhat5安装oracle10g

    安装缺失的包: 用 root 用户身份运行以下命令: rpm -q gcc make binutils openmotif setarch compat-db compat-gcc compat-gc ...

  8. cmd 运行 svn 亲测!!!

    如果之前安装了svn客户端,但是一直提示svn停止工作的话就可以用cmd去操作svn更新和提交了:或者可以直接用别的代码IDE(包含svn插件的)去进行svn的操作. 接下来我说说windows如何用 ...

  9. 【sqli-labs】 less14 POST - Double Injection - Single quotes- String -twist (POST型单引号变形双注入)

    名字和less13一样? 看了下源码对比 less13 less14 less14应该是双引号吧 出错 构造永真登陆

  10. Bootstrap 模态框(Modal)带参数传值实例

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 为了实现父窗体与其的交互,通常需要向其传值,实现 ...