IoC实践--用Unity实现MVC5.0的IoC控制反转方法
在MVC中,控制器依赖于模型对数据进行处理,也可以说执行业务逻辑。我们可以使用依赖注入(DI)在控制层分离模型层,这边要用到Repository模式,在领域驱动设计(DDD)中,Repository翻译为仓储,顾名思义,就是储存东西的仓库,可以理解为一种用来封装存储,读取和查找行为的机制,它模拟了一个对象集合。使用依赖注入(DI)就是对Repository进行管理,用于解决它与控制器之间耦合度问题,下面我们一步一步做一个简单示例。
安装Unity
首先我们需要新建一个UnityMVCDemo项目(ASP.NET MVC4.0),选择工具-库程序包管理器-程序包管理控制台,输入“Install-Package Unity.Mvc4”命令,VS2010可能需要先安装NuGet。

或者通过工具-库程序包管理器-管理解决方案的 NuGet 程序包,通过联机搜索“Unity.Mvc4”进行安装。

在安装过程中可能会遇到下面这样错误:

根据异常信息,可以肯定是项目的.net framework版本无法安装Unity,这种安装VS会自动搜索Unity最新版本,但是最新版本往往有. net framework版本要求,不知道有没有指定Unity版本安装,可以看到我们安装的是Unity3.0版本,修改一下项目. net framework的版本为4.5,重新安装就可以了。
安装Unity成功后,我们发现项目中多了“Microsoft.Practices.Unity”和“Microsoft.Practices.Unity.Configuration”两个引用,还有一个Bootstrapper类文件,Bootstrapper翻译为引导程序,也就是Ioc容器。

1 public static class Bootstrapper
2 {
3 public static IUnityContainer Initialise()
4 {
5 var container = BuildUnityContainer();
6
7 DependencyResolver.SetResolver(new UnityDependencyResolver(container));
8
9 return container;
10 }
11
12 private static IUnityContainer BuildUnityContainer()
13 {
14 var container = new UnityContainer();
15
16 // register all your components with the container here
17 // it is NOT necessary to register your controllers
18
19 // e.g. container.RegisterType<ITestService, TestService>();
20 RegisterTypes(container);
21
22 return container;
23 }
24
25 public static void RegisterTypes(IUnityContainer container)
26 {
27
28 }
29 }

添加服务层
首先我们添加一个Article实体类:

1 /// <summary>
2 /// Article实体类
3 /// </summary>
4 public class Article
5 {
6 public int Id { get; set; }
7 public string Title { get; set; }
8 public string Author { get; set; }
9 public string Content { get; set; }
10 public DateTime CreateTime { get; set; }
11 }

一般Repository都有一些相似的操作,比如增删改查,我们可以把它抽象为IArticleRepository接口,这样控制器依赖于抽象接口,而不依赖于具体实现Repository类,符合依赖倒置原则,我们才可以使用Unity进行依赖注入。

1 /// <summary>
2 /// IArticleRepository接口
3 /// </summary>
4 public interface IArticleRepository
5 {
6 IEnumerable<Article> GetAll();
7 Article Get(int id);
8 Article Add(Article item);
9 bool Update(Article item);
10 bool Delete(int id);
11 }

创建ArticleRepository,依赖于IArticleRepository接口,实现基本操作。

1 public class ArticleRepository : IArticleRepository
2 {
3 private List<Article> Articles = new List<Article>();
4
5 public ArticleRepository()
6 {
7 //添加演示数据
8 Add(new Article { Id = 1, Title = "UnityMVCDemo1", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
9 Add(new Article { Id = 2, Title = "UnityMVCDemo2", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
10 Add(new Article { Id = 3, Title = "UnityMVCDemo2", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
11 }
12 /// <summary>
13 /// 获取全部文章
14 /// </summary>
15 /// <returns></returns>
16 public IEnumerable GetAll()
17 {
18 return Articles;
19 }
20 /// <summary>
21 /// 通过ID获取文章
22 /// </summary>
23 /// <param name="id"></param>
24 /// <returns></returns>
25 public Article Get(int id)
26 {
27 return Articles.Find(p => p.Id == id);
28 }
29 /// <summary>
30 /// 添加文章
31 /// </summary>
32 /// <param name="item"></param>
33 /// <returns></returns>
34 public Article Add(Article item)
35 {
36 if (item == null)
37 {
38 throw new ArgumentNullException("item");
39 }
40 Articles.Add(item);
41 return item;
42 }
43 /// <summary>
44 /// 更新文章
45 /// </summary>
46 /// <param name="item"></param>
47 /// <returns></returns>
48 public bool Update(Article item)
49 {
50 if (item == null)
51 {
52 throw new ArgumentNullException("item");
53 }
54
55 int index = Articles.FindIndex(p => p.Id == item.Id);
56 if (index == -1)
57 {
58 return false;
59 }
60 Articles.RemoveAt(index);
61 Articles.Add(item);
62 return true;
63 }
64 /// <summary>
65 /// 删除文章
66 /// </summary>
67 /// <param name="id"></param>
68 /// <returns></returns>
69 public bool Delete(int id)
70 {
71 Articles.RemoveAll(p => p.Id == id);
72 return true;
73 }
74 }

IArticleRepository类型映射
上面工作做好后,我们需要在Bootstrapper中的BuildUnityContainer方法添加此类型映射。

1 private static IUnityContainer BuildUnityContainer()
2 {
3 var container = new UnityContainer();
4
5 // register all your components with the container here
6 // it is NOT necessary to register your controllers
7
8 container.RegisterType<IArticleRepository, ArticleRepository>();
9
10 // e.g. container.RegisterType<ITestService, TestService>();
11 RegisterTypes(container);
12
13 return container;
14 }

我们还可以在配置文件中添加类型映射,UnityContainer根据配置信息,自动注册相关类型,这样我们就只要改配置文件了,当然推荐是这种方法,配置文件:

1 <configSections>
2 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
3 Microsoft.Practices.Unity.Configuration" />
4 </configSections>
5 <unity>
6 <containers>
7 <container name="defaultContainer">
8 <register type="UnityMVCDemo.Models.IArticleRepository, UnityMVCDemo" mapTo="UnityMVCDemo.Models.ArticleRepository, UnityMVCDemo"/>
9 </container>
10 </containers>
11 </unity>

注意configSections节点要放在configuration节点下的第一个节点,关于Unity的配置文件配置参照http://www.cnblogs.com/xishuai/p/3670292.html,加载配置文件代码:
1 UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
2 configuration.Configure(container, "defaultContainer");
上面这段代码替换掉上面使用的RegisterType方法。
服务注入到控制器
在ArticleController中我们使用是构造器注入方式,当然还有属性注入和方法注入,可以看到ArticleController依赖于抽象IArticleRepository接口,而并不是依赖于ArticleRepository具体实现类。

1 public class ArticleController : Controller
2 {
3 readonly IArticleRepository repository;
4 //构造器注入
5 public ArticleController(IArticleRepository repository)
6 {
7 this.repository = repository;
8 }
9
10 public ActionResult Index()
11 {
12 var data = repository.GetAll();
13 return View(data);
14 }
15 }

Global.asax初始化
做完上面的工作后,我们需要在Global.asax中的Application_Start方法添加依赖注入初始化。

1 // Note: For instructions on enabling IIS6 or IIS7 classic mode,
2 // visit http://go.microsoft.com/?LinkId=9394801
3 public class MvcApplication : System.Web.HttpApplication
4 {
5 protected void Application_Start()
6 {
7 AreaRegistration.RegisterAllAreas();
8
9 WebApiConfig.Register(GlobalConfiguration.Configuration);
10 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
11 RouteConfig.RegisterRoutes(RouteTable.Routes);
12
13 Bootstrapper.Initialise();
14 }
15 }

后记
示例代码下载:http://files.cnblogs.com/files/sexintercourse/UnityMVCDemo.rar
后来经过了一系列的改进,我们后来的代码。
代码下载http://files.cnblogs.com/files/sexintercourse/UnityMVCDemo20.zip
IoC实践--用Unity实现MVC5.0的IoC控制反转方法的更多相关文章
- IoC实践--用Autofac实现MVC5.0的IoC控制反转方法
Autofac是一个.net平台下发性能还不错的IoC框架,利用它可以实现依赖注入和控制反转,使自己的软件模块之间的耦合性大大降低,让软件扩展.维护更加容易.控制反转(Inversion of Con ...
- Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)
一.思想理解 Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运行.S ...
- 控制反转IOC与依赖注入DI【转】
转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...
- 控制反转IOC与依赖注入DI - 理论篇
学无止境,精益求精 十年河东十年河西,莫欺少年穷 昨天是五一小长假归来上班的第一天,身体疲劳,毫无工作热情.于是就看看新闻,喝喝茶,荒废了一天 也就在昨天,康美同事张晶童鞋让我学习下IOC的理论及实现 ...
- 20181123_控制反转(IOC)和依赖注入(DI)
一. 控制反转和依赖注入: 控制反转的前提, 是依赖倒置原则, 系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖 (依赖抽象,而不是细节) 如果要想做到控制反转(IOC), 就必须要使 ...
- IOC(控制反转)的理解
1.IOC的理论背景 我们知道在面向对象设计的软件系统中,它的底层都是由N个对象构成的,各个对象之间通过相互合作,最终实现系统地业务逻辑[1]. 图1 软件系统中耦合的对象 如果我们打开机械式手表的后 ...
- Spring详解(二)------IOC控制反转
我相信提到 Spring,很多人会脱口而出IOC(控制反转).DI(依赖注入).AOP等等概念,这些概念也是面试官经常问到的知识点.那么这篇博客我们就来详细的讲解 IOC控制反转. ps:本篇博客源码 ...
- 接上一篇:(四) 控制反转(IOC)/ 依赖注入(DI)
spring 核心功能:beans.core.context.expression Spring设计理念 Spring是面向Bean的编程 Spring三个核心组件(Core.Context.Bean ...
- Spring详解(一)------IOC控制反转
1.什么是 IOC? IOC-Inversion of Control,即控制反转.它不是什么技术,而是一种设计思想. 传统的创建对象的方法是直接通过 new 关键字,而 spring 则是通过 IO ...
随机推荐
- ADB理解
在做手机测试时候,经常用到的命令就是adb.如adb shell,adb devices,adb logcat等等 那么什么是adb,怎么用呢? 一.adb adb的全称为Android Debug ...
- Phone Gap [error] cmd: Command failed with exit code 1
下投票 我不知道如何解决这个问题,但尝试了这一点,将解决肯定. 这是由于ANT工具找不到的tools.jar在JRE lib目录下.当我从复制的tools.jar JDK的lib目录下,以JRE li ...
- topsort | | jzoj[1226] | | NOIP2003神经网络
今天终于通过了那道永远都看不懂题目的神经网络... 所谓拓扑排序,就是在有向无环图中,根据已经有的点和点之间的关系进行排序 引用jzyz教材上的栗子:比如说奶牛比较食量大小,我现在拿到的是cow[i] ...
- java string类型的初始化
以下基本上是java string类型最常用的三种方法 new string()就不介绍了 基本等同于第三种 String a; 申明一个string类型的 a,即没有在申请内存地址,更没有在内存 ...
- C#调用百度地图API经验分享(一)
最近客户提了一个需求,要在网站中添加百度地图的显示,其实原来是有谷歌地图的,但由于谷歌在大陆遭到封杀,只好再给用户增加一个选择了. 下面我将自己最近整理的一些知识分享给大家. 如何使用百度地图API: ...
- 20145225《Java程序设计》 实验四 Android开发基础
20145225<Java程序设计> 实验四 Android开发基础 实验报告 实验内容 安装Android Studio 运行安卓AVD模拟器 使用安卓运行出虚拟手机并显示HelloWo ...
- 计算机图形学——OpenGL开发库开发库
vc++6.0 有 OpenGL 的东西.有头文件 GL.H, GLAUX.H, GLU.H 但没有 GLUT 软件包/工具包 如果想使用glut.h的话必须自己添加. 首先下载 OpenGL开发库, ...
- UE简单操作
一:UE恢复默认配置 1.开始--运行-- “%APPDATA%” 回车 . 2. 找到并打开 IDMComp 文件夹.将文件夹“UltraEdit”整个给删除. 3.重 ...
- 斯坦福第十九课:总结(Conclusion)
19.1 总结和致谢 欢迎来到<机器学习>课的最后一段视频.我们已经一起学习很长一段时间了.在最后视频中,我想快速地回顾一下这门课的主要内容,然后简单说几句想说的话. 作为这门课的结束时 ...
- Source Depot 使用总结
MS使用的Source Depot方案,主要是控制软件版本,类似的软件有SVN等,Source Depot一般使用起来也比较方便,可以灵活的配置,只要有访问权限,就可以下到对应的源代码文件. SD使用 ...