不用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团队已经使用依赖注入的概念好几年了在那时 ...
随机推荐
- 提升GDI画图的效率
假设我们要画一个坐标图,里面可能还需要画网络线.XY各个单位的值.曲线或直线等,可能的函数代码如下: void OnPaint () { CPaintDC dc (this); DrawXY (&am ...
- ZOJ 2588 Burning Bridges(求含重边的无向连通图的割边) - from lanshui_Yang
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little country ...
- CentOS安装某个命令的办法如locate
在Linux使用命令时,有时候因为系统精简的原因,某些命令可能没有安装locate包,例如你要输入的命令是locate 发现没有该命令,修复办法如下: 一.使用如下命令查询缺失命令的包名 #yum l ...
- 短小实用 渗透用的Python小脚本
渗透的很多时候,找到的工具并不适用,自己码代码才是王道,下面三个程序都是渗透时在网络上找不到合适工具,自己辛苦开发的,短小实用. 一.记录root密码小工具 root.py #!/usr/bin/py ...
- 1.5.8 语言分析器(Analyzer)
语言分析器(Analyzer) 这部分包含了分词器(tokenizer)和过滤器(filter)关于字符转换和使用指定语言的相关信息.对于欧洲语言来说,tokenizer是相当直接的,Tokens被空 ...
- javass 视频笔记二 (关键字,标示符,常量变量,运算符和if-else)
1,java的关键字和标识符2,java的基本数据类型3,变量和常量4,java的运算符5,if-else if - else表达式1,java的关键字和标识符 1.1,所有关键字都要小写 ...
- C# 使用代码来操作 IIS
由于需要维护网站的时候,可以自动将所有的站点HTTP重定向到指定的静态页面上. 要操作 IIS 主要使用到的是“Microsoft.Web.Administration.dll”. 该类库不可以在引用 ...
- TFS 2010 使用手册(一)安装与配置
本文转自cnblogs 大辉狼 的文章: http://www.cnblogs.com/wph1129/archive/2010/11/10/1873348.html http://www.cnblo ...
- 精通CSS高级Web标准解决方案(1-2 层叠与特殊性)
层叠与特殊性 选择器的特殊性分成四个等级,a.b.c . d 如果样式是行内样式,那么a=1 b=ID选择器的总数 c=类.伪类.属性选择器的总数 d=标签选择器与伪元素选择器数量 例如:style ...
- 剑指Offer47 不用加减乘除做加法
/************************************************************************* > File Name: 47_AddTwo ...