上一篇《我在项目中运用 IOC(依赖注入)--入门篇》只是简单的使用 IOC。实际项目使用 IOC 的情景复杂多了,比如说,构造函数有多个参数,有多个类继承同一个接口... Unity都有解决方法。首先回顾一下入门篇的项目需求:项目中数据统计功能,它下面有三种不同的统计类型,需要与数据库交互,然后展示到页面,在这篇中我们接着这个需求继续扩充。

【没有接口】

新增Model 层,LoginUser 当前登录人。无接口的怎样用IOC 创建对象。代码如下

Model.LoginUser loginUser = container.Resolve<Model.LoginUser>();

【多个子类】

DAL 层 新增ShowResult2 方法

public class Analyse:IDAL.IAnalyse
{
public void ShowResult()
{
Console.WriteLine("分析底层数据库交互");
} public void ShowResult2()
{
Console.WriteLine("这是B类分析底层数据库交互");
}
}

BLL层 新增 AnalyseB ,继承 IAnalyse

 public class AnalyseB:IBLL.IAnalyse
{
////使用依赖注入
[Dependency]
public IDAL.IAnalyse dal { get; set; } public void ShowResult()
{
dal.ShowResult2();
}
}

按照入门篇的步骤,需要在core 层 DependencyRegister 修改 DependencyRegisterContainer 方法

public static IUnityContainer DependencyRegisterContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
.RegisterType<IDAL.IAnalyse, DAL.Analyse>()
.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>();
return container;
}

我们发现IBLL.IAnalyse被两个类继承,所以在 IOC 容器中注入了两次。这样写能区分开吗?我们先在UI 层增加显示代码

/// <summary>
/// 多个类继承同一个接口
/// </summary>
private static void IOCMethod4()
{
IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>();
bll.ShowResult();
}

运行程序,发现每次只会出现 AnalyseB 类的结果。即 IAnalyse=最后注册的类型 。Unity 的 RegisterType 方法有个参数string name。用key来区分子类型。修改代码

//core 层
public static IUnityContainer DependencyRegisterContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
.RegisterType<IDAL.IAnalyse, DAL.Analyse>()
.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B");
return container;
} //// UI 层
private static void IOCMethod4()
{
IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B");
bll.ShowResult();
} ////同时运行 IOCMethod2() 和 IOCMethod4()

结果

这样就是实现了子类多个的 IOC 容器注册。(注意,key一定要区分大小写)

 【带参的构造函数】

Web程序与数据库交互的时候,需要从前台获取查询条件,我在 AnalyseB 中写了一个带有 string 类型的构造函数。代码如下

 public class AnalyseB:IBLL.IAnalyse
{
public string StrWhere { get; set; } /// <summary>
/// 查询条件的构造函数
/// </summary>
/// <param name="strWhere"></param>
public AnalyseB(string strWhere)
{
this.StrWhere = strWhere;
} ////使用依赖注入
[Dependency]
public IDAL.IAnalyse dal { get; set; }
public void ShowResult()
{
dal.ShowResult2(StrWhere);
}
}
//// 修改 core 层 容器注册方法
public static IUnityContainer DependencyRegisterContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
.RegisterType<IDAL.IAnalyse, DAL.Analyse>()
.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(string))));
return container;
} ////UI 层调用代码如下
private static void IOCMethod4()
{
IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B",
new ParameterOverride("strWhere", " WHERE 1=1 "));
bll.ShowResult();
}

AnalyseB 构造函数带有string 类型的参数,在 容器注册的时候,需要注册 参数的类型  new InjectionConstructor(typeof(string),typeof(param2),...) (这里也可以是常量)。调用时用ParameterOverride(构造函数参数名,参数值) 来重新给参数赋值。

如果参数是其它类型又怎么办。例如数据以表格形式呈现时,需要分页。我在BLL 层加了一个分页接口。修改代码

////新增分页接口
public interface IPager
{
string GetPager();
} public class AnalysePager : IBLL.IPager
{
public string GetPager()
{
return "数据已分页";
}
} public class AnalyseB:IBLL.IAnalyse
{
public string StrWhere { get; set; }
public IBLL.IPager Pager { get; set; } public AnalyseB(IBLL.IPager pager, string strWhere)
{
this.Pager = pager;
this.StrWhere = strWhere + pager.GetPager();
} ////使用依赖注入
[Dependency]
public IDAL.IAnalyse dal { get; set; } public void ShowResult()
{
dal.ShowResult2(StrWhere);
}
} ////修改core层 方法
public class DependencyRegister
{
public static IUnityContainer DependencyRegisterContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
.RegisterType<IDAL.IAnalyse, DAL.Analyse>()
.RegisterType<IBLL.IPager,BLL.AnalysePager>()
.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string))));
return container;
}
} ////UI 层代码不变

运行结果:

【属性注入】

修改一下构造函数,把参数 IPager 提成属性。 代码如下

public class AnalyseB:IBLL.IAnalyse
{
public string StrWhere { get; set; } public IBLL.IPager Pager { get; set; } /// <summary>
/// 查询条件的构造函数
/// </summary>
/// <param name="strWhere"></param>
public AnalyseB(IBLL.IPager pager, string strWhere)
{
this.Pager = pager;
this.StrWhere = strWhere + pager.GetPager();
}
        public AnalyseB(string strWhere)
{
this.StrWhere = strWhere;
} ////使用依赖注入
//[Dependency]
public IDAL.IAnalyse dal { get; set; } public void ShowResult()
{
StrWhere += Pager.GetPager();
dal.ShowResult2(StrWhere);
} //// core
public static IUnityContainer DependencyRegisterContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
.RegisterType<IDAL.IAnalyse, DAL.Analyse>()
.RegisterType<IBLL.IPager, BLL.AnalysePager>()
//.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-C", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string))));
.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-D", new InjectionMember[]
{
new InjectionConstructor(typeof (string)),
new InjectionProperty("Pager"),
new InjectionProperty("dal"),
});
return container;
}

自己在实际使用过程总结了几点:

1.使用属性注入,属性不能再构造函数中使用,否则会报为实例化对象异常。(关于这点自己持怀疑态度,有可能是自己不正确的使用造成的。希望和大家讨论)

2.BLL.AnalyseB 本身有个属性 dal. 如果使用属性注入,则所有属性都须加入 InjectionMember[] .

3.最好使用构造注入。

(以上三点是在项目使用过程中,自己总结出来。非权威,非标准,有不对的地方希望大家指出。`(*∩_∩*)′)

【方法注入】

除开构造注入,属性注入,还有方法注入。使用与属性注入差不多。方法注入尚没有在实际项目中应用过,下面例子是参考其它两种注入方法写的

////修改此类,增加字段_pager 和 方法 SetPager
public class AnalyseB:IBLL.IAnalyse
{
public string StrWhere { get; set; } public IBLL.IPager Pager { get; set; } public IBLL.IPager _pager; public void SetPager(IBLL.IPager pager)
{
this._pager = pager;
} /// <summary>
/// 查询条件的构造函数
/// </summary>
/// <param name="strWhere"></param>
public AnalyseB(IBLL.IPager pager, string strWhere)
{
this.Pager = pager;
this.StrWhere = strWhere + pager.GetPager();
} public AnalyseB(string strWhere)
{
this.StrWhere = strWhere;
} ////使用依赖注入
[Dependency]
public IDAL.IAnalyse dal { get; set; } public void ShowResult()
{
//StrWhere += Pager.GetPager();
StrWhere += this._pager.GetPager();
dal.ShowResult2(StrWhere);
} ////增加core层的注入方式
container..RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-E", new InjectionMember[]
{
new InjectionConstructor(typeof (string)),
new InjectionMethod("SetPager",container.Resolve<IBLL.IPager>()),
}); ////UI 层调用
/// <summary>
/// 方法注入
/// </summary>
public static void IOCMethod6()
{
IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-E",
new ParameterOverride("strWhere", " WHERE 1=1 "));
bll.ShowResult();
}

(个人觉得方法注入很鸡肋,其实就是属性注入)

以上是我在项目运用过程中总结出来的一些心得,尚有许多不足的地方,先抛砖引玉,与大家共同讨论,共同学习。

【源码下载】

我在项目中运用 IOC(依赖注入)--实战篇的更多相关文章

  1. Android开源项目发现--- 工具类依赖注入DI篇(持续更新)

    通过依赖注入减少View.服务.资源简化初始化,事件绑定等重复繁琐工作 1. AndroidAnnotations(Code Diet) android快速开发框架 项目地址:https://gith ...

  2. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

  3. 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...

  4. Spring 之 控制反转(IoC), 依赖注入(DI)和面向切面(AOP)

    关于依赖注入, 这篇博文写的非常简单易懂. https://github.com/android-cn/blog/tree/master/java/dependency-injection 此外, 博 ...

  5. ASP.NET MVC IOC依赖注入之Autofac系列(二)- WebForm当中应用

    上一章主要介绍了Autofac在MVC当中的具体应用,本章将继续简单的介绍下Autofac在普通的WebForm当中的使用. PS:目前本人还不知道WebForm页面的构造函数要如何注入,以下在Web ...

  6. ASP.NET MVC IOC依赖注入之Autofac系列(一)- MVC当中应用

    话不多说,直入主题看我们的解决方案结构: 分别对上面的工程进行简单的说明: 1.TianYa.DotNetShare.Model:为demo的实体层 2.TianYa.DotNetShare.Repo ...

  7. 浅谈(IOC)依赖注入与控制反转(DI)

    前言:参考了百度文献和https://www.cnblogs.com/liuqifeng/p/11077592.html以及http://www.cnblogs.com/leoo2sk/archive ...

  8. Spring学习-spring核心机制-IOC依赖注入

    转载自:http://www.cnblogs.com/chenssy/archive/2012/11/11/2765266.html 今天复习一下spring两大特性之一:IOC依赖注入,看了一下大佬 ...

  9. 【17MKH】我在框架中对.Net依赖注入的扩展

    说明 依赖注入(DI)是控制反转(IoC)的一种技术实现,它应该算是.Net中最核心,也是最基本的一个功能.但是官方只是实现了基本的功能和扩展方法,而我呢,在自己的框架 https://github. ...

随机推荐

  1. 使用JQuery插件Jcrop进行图片截取

    Jcrop插件本身并不含有图片截取功能,它仅仅是在前端层面构建一套截取动画效果并产生4个坐标点,插件使用者将这4个坐标点传回至服务器接口上进行截取操作.其优点是具有较高的通用性.浏览器兼容性(IE6+ ...

  2. 【JS深入学习】——事件代理/事件委托

    事件代理/事件委托(event delegation) 需求一:当一个div内部有多个事件发生,给每个元素逐个添加事件十分麻烦... 需求二:在项目中我们常常需要动态的添加元素,不可避免的需要为那些未 ...

  3. day 42 mysql 数据库(2)

    前情提要: 本节继续学习数据库   一:ddl 创建表 >字段名 >数据类型 >约束规则 >显示建表语句 修改表: 二:数据类型 >数值类型 >小数类型 >字 ...

  4. Jira API传字符串的换行问题 (文本编辑器使用)

    因为jira的文本编辑器自动进行了2次转义,如果从API过来的文本换行需要手动处理.吐血. net里: desc = desc.Replace("\n", "\\n&qu ...

  5. 【NOIP2013】 华容道 bfs预处理+bfs

    这一题我们考虑一个最裸的算法: 我们设$dp[i][j][k][l]$表示当前棋子在$(i,j)$且空格在$(k,l)$时的最小步数 然后显然随便转移一下就好了,时间复杂度为$O(q(nm)^2)$. ...

  6. POJ 1083

    #include<iostream> #include<stdio.h> #include<algorithm> #define MAXN 400 using na ...

  7. Python 1行代码实现文本分类(实战笔记),含代码详细说明及运行结果

    Python 1行代码实现文本分类(实战笔记),含代码详细说明及运行结果 一.详细说明及代码 tc.py =============================================== ...

  8. zookeeper知识点学习

    单机模式配置: Zookeeper 的启动脚本在 bin 目录下,Linux 下的启动脚本是 zkServer.sh 在你执行启动脚本之前,还有几个基本的配置项需要配置一 下,Zookeeper 的配 ...

  9. 监督学习——决策树理论与实践(上):分类决策树

    1. 介绍         决策树是一种依托决策而建立起来的一种树.在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象/分类,树中的每一个分叉路 ...

  10. Spring Security构建Rest服务-0200-搭建项目

    一.代码结构: 二.使用Springmvc开发restful API 传统url和rest区别: 三.写代码 1,编写RestfulAPI的测试用例:使用MockMvc伪造mvc package co ...