不用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团队已经使用依赖注入的概念好几年了在那时 ...
随机推荐
- npm常用命令->nodejs
npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...
- LeetCode18 4Sum
题意: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...
- WPF 之 style文件的引用
总结一下WPF中Style样式的引用方法. 一.内联样式: 直接设置控件的Height.Width.Foreground.HorizontalAlignment.VerticalAlignment等属 ...
- 关键字提取算法之TF-IDF扫盲
TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术.TF-IDF是一种统计方法,用以评估一字词对于一个文件集或 ...
- solr--搜索参数随笔
1.默认搜索域.查询域的关系 qf字段的配置:query fields,指定solr从哪些field中搜索 在solrj中设置如下: params.setParam("qf", & ...
- a 中调用js的几种方法
我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题 ...
- [Android 开源项目学习]Android的UITableView(1)
最近由于项目加急,手里有好多看了差不多的开源项目,其中好多是大家经常用到的.图片的缓存BitmapFun(Android的文档中),AfinalMap,下拉刷新PullToRefresh等等 ...
- [转]使用 HTML5 索引型数据库的待办事项简要列表
本文转自:http://www.html5rocks.com/zh/tutorials/indexeddb/todo/ <!DOCTYPE html><html> <h ...
- CF Preparing Olympiad (DFS)
Preparing Olympiad time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- hdu-5505(数论)
题目链接: GT and numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...