不用Unity库,自己实现.NET轻量级依赖注入
在面向对象的设计中,依赖注入(IoC)作为一种重要的设计模式,主要用于削减计算机程序的耦合问题,相对于Java中的Spring框架来说,微软企业库中的Unity框架是目前.NET平台中运用比较广泛的依赖注入框架之一(还有的Spring.NET等)。但是对于这些“官方版本”的强大依赖注入框架,通常使用和配置都比较复杂,我个人更希望实现一种“约定胜于配置”轻量级IoC框架。
实现依赖注入主要是运用C#中的反射技术,通过配置文件,把代码的实现注入到接口中。用户只是访问接口,对于接口的实现一概不知,可以有效地对接口和实现进行解耦,在介绍代码之前,先来看一下我们的配置文件:
<appSettings> <!--依赖注入配置--> <add key="Domain.Entity.IRepository" value="Infrastructure.Repository"/> </appSettings>
Domain.Entity.IRepository与Infrastructure.Repository都是.NET中的程序集(dll),其中Domain.Entity.IRepository中定义了领域模型中所需要的仓储接口,Infrastructure.Repository中定义了仓储接口的实现。领域模型需要访问数据的时候,并不是直接访问ADO或者ORM,而是通过访问Domain.Entity.IRepository中的仓储接口,再通过依赖注入把Infrastructure.Repository中的实现注入到接口中,这样就有效隔离了领域模型对数据实现的依赖,如果后期需要更换数据库或ORM框架,只需要实现另一个Infrastructure.Repository,并更新依赖注入配置即可。
下面介绍轻量级依赖注入的实现方法,先贴代码:
public sealed class DependencyInjector { /// <summary> /// 根据名称和构造函数的参数加载相应的类 /// </summary> /// <typeparam name="T">需要加载的类所实现的接口</typeparam> /// <param name="className">类的名称</param> /// <param name="args">构造函数的参数(默认为空)</param> /// <returns>类的接口</returns> public static T GetClass<T>(string className, object[] args = null) where T : class { //获取接口所在的命名空间 string factoryName = typeof(T).Namespace; //通过依赖注入配置文件获取接口实现所在的命名空间 string dllName = ConfigurationManager.AppSettings[factoryName]; //获取类的全名 string fullClassName = dllName + "." + className; //根据dll和类名,利用反射加载类 object classObject = Assembly.Load(dllName).CreateInstance(fullClassName, true, BindingFlags.Default, null, args, null, null); ; return classObject as T; } }
代码中的typeof(T).Namespace,其中T是接口的类型,获取接口的命名空间以后,再通过我们的配置文件,就可以获取类的命名空间,再加上类名,通过c#的反射机制,就可以加载类的实现。也许你会说,我们只知道接口,并不知道类名是什么,别急,我们对该代码进一步进行封装:
public sealed class IoC { /// <summary> /// //通过接口名称和构造函数的参数得到实现 /// </summary> /// <typeparam name="T">接口类型</typeparam> /// <param name="args">构造函数的参数</param> /// <returns>接口的实现</returns> public static T Resolve<T>(object[] args = null) where T : class { //获取类名 ); //通过判断fullName中是否包含`符号来判断是否是泛型 string fullName = typeof(T).FullName; int flag = fullName.IndexOf('`'); //如果是泛型,需要特殊处理 ) { int dot = fullName.LastIndexOf('.', flag); //这里去掉方法名前面的点和I className = fullName.Substring(dot + ); } return DependencyInjector.GetClass<T>(className, args); } }
在这里我们就用到了上面所说的”约定胜于配置“,我们约定接口的名称是在类名的前面加上I,并且接口和实现必须是独立的程序集。如果类名是Helper,那么接口的名字就必须是IHelper,我们通过去掉接口前面的I来获得实现的类名。如果是泛型接口,还需要进行特殊的处理,这里我们通过判断类型的全名中是否包含”`“符号来判断是否泛型接口。
下面举一个使用该依赖注入的例子:
public static Book GetById(string bookID) { IRepository<Book> bookRep = IoC.Resolve<IRepository<Book>>(); return bookRep.GetByKeys(bookID); } public int GetBookCount() { IBookRepository bookRep = IoC.Resolve<IBookRepository>(); return bookRep.GetCount(); }
在这里我们是不知道接口的实现的,通过我们封装的IoC.Resolve方法,可以把我们配置文件中的接口实现”注入到接口“中,通过这种解耦的方式,后期我可以更加灵活地对代码进行重构。
不用Unity库,自己实现.NET轻量级依赖注入的更多相关文章
- 不用Unity库,利用.NET动态代理自己实现AOP
AOP意为面向切面的程序设计,主要表现为对不同的代码逻辑进行隔离,从而降低不同业务逻辑之间的耦合性,AOP又理解为“横切”,可以在不改变原有实现的情况下,对代码进行拦截和扩展,如果原有设计像一个瓶子, ...
- Unity轻量级依赖注入容器
一.前言 Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.在Nuget里安装unity
- Unity文档阅读 第二章 依赖注入
Introduction 介绍Chapter 1 outlines how you can address some of the most common requirements in enterp ...
- 【Unity】微软的一款依赖注入组件
前言 前面学习了autofac这个依赖注入组件,本来是打算写在一起的,因为这个组件没打算像autofac一样详细的写,只是写下以前自己鼓捣玩搭建框架然后使用的一个依赖注入组件,并且也是进行了封装使用. ...
- 使用Unity解耦你的系统—PART3——依赖注入
继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系.Unity内置所有的生命周期管理使用介绍,及Unity的Regist ...
- 使用Unity 实现ASP.NET Web API 依赖注入
DI/IoC 的设计前面已经讲过好几次了,简单的一段话说明就是:「目标对象与外部相依的方式仅相依于 interface,而相依 interface 的 instance 透过 constructor ...
- 理解依赖注入(IOC)和学习Unity
资料1: IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection). 作用:将各层的对象以松耦合的方式组织在一 ...
- 依赖注入与Unity(一) 介绍
在你学习依赖注入和Unity之前,你需要明白你为什么要使用它们.为了明白为什么要使用它们,你应该明白依赖注入和Unity能够帮助你解决什么类型的问题.作为介绍部分,这一章不会涉及太多关于Uni ...
- 通过Unity依赖注入
前言 Unity容器的思想起始于我在为Web Client Sofitware Factory项目工作的时候,微软的patterns&practices团队已经使用依赖注入的概念好几年了在那时 ...
随机推荐
- ubuntu 设置IP,设置网关
1. 检验是否可以连通,就使用ping命令ping 网关 开始的时候总是现实unreachable 2. 设置IP sudo ifconfig eth0 133.133.133.190 netmask ...
- DataContractJsonSerializer和JavaScriptSerializer内部实现差异
定义一个下面这样的类,此类有Serializable属性,并且有一个属性的定义没有使用自动属性来实现. [Serializable] public class Users { public int U ...
- centos下查看rpm包安装位置
1.如何安装rpm软件包 rpm -ivh your-package.rpm其中your-package.rpm是你要安装的rpm包的文件名,一般置于当前目录下. 2.如何卸载rpm软件包使用命令 r ...
- Oracle基础 exp/imp命令
一.导出方式: 使用exp/imp方式导出数据分为四种方式: 1.表方式导出:一个或多个指定的表,包括表的定义.表数据.表的所有者授权.表索引.表约束,以及创建在该表上的触发器.也可以只导出结构,不导 ...
- oracle PL/SQL(procedure language/SQL)程序设计之触发器(trigger)
创建触发器 触发器类似于过程和函数,都拥有声明.执行和异常处理过程的带名PL/SQL块.与包类似,触发器必须存储在数据库中.前面已经讲过,过程是显式地通过过程调用执行的,同时过程调用可以传递参数.与之 ...
- UWP源码——Unit Test
之前我们讨论了涨姿势UWP的RSS数据源获取,以及作为文件存储到本地,再将数据转化成Model对象.这部分非UI的内容非常适合添加Unit Test.不涉及UI的话,UT写起来简单高效,很是值得投入一 ...
- Angularjs 中使用指令绑定点击事件
项目中,模板中的菜单是jQuery控制的,在Angularjs中就运行不到了,因为菜单项是ng-repeat之后的. 如html <ul id="main-menu"> ...
- CSS图片翻转例子
dfdfdfdfdf <!DOCTYPE html> <html> <head> <meta charset=" ...
- $(function(){})与$(document).ready(function(){})
$(function(){ //jq ready()的简写 }); $(document).ready(function(){ // }); 或者: $().ready(function(){ //j ...
- js使用CSS将图片转换成黑白(灰色、置灰)
详细内容请点击 可能早就知道,像汶川这种糟糕的日子网站全灰在IE下是可以轻松实现的(filter: gray;),不过,当时,其他浏览器是无解的. 不过,时代发展,如今,CSS3的逐步推进,我们也开始 ...