依赖注入(IOC)二
依赖注入(IOC)二
上一章我们讲了构造注入与设值注入,这一篇我们主要讲接口注入与特性注入。
接口注入
接口注入是将抽象类型的入口以方法定义在一个接口中,如果客户类型需要获得这个方法,就需要以实现这个接口的方式完成注入。实际上接口注入有很强的侵入性,除了要求客户类型增加前面两种方式所需要的代码外,还必须显示地定义一个新的接口并要求客户类型实现它。
//定义需要注入ITimeProvider的类型
interface IobjectWithTimeProvider
{
ITimeProvider TimeProvider { get; set; }
} //通过接口方式实现注入
public class Client:IobjectWithTimeProvider
{
public ITimeProvider TimeProvider { get; set; }
}
Unit Test
[TestClass]
public class TestClent
{
[TestMethod]
public void TestMethod1()
{
ITimeProvider timeProvider =
(new Assembler()).Create<ITimeProvider>(); Assert.IsNotNull(timeProvider);//确认可以正常获得抽象类型实例 IObjectWithTimeProvider objectWithProvider = new Client();
objectWithProvider.TimeProvider = timeProvider;//通过接口方式注入 }
}
随着C#语言的发展,接口注入可以采用与设值注入方式相似的方式实现,而且看上去很“Lamada化”。因为不用真正去实现接口,而是通过泛型参数的方式实现,可以说泛型为C#实现接口注入提供了“新生”。
/// <summary>
/// 通过泛型参数实现接口注入
/// </summary>
/// <typeparam name="T">待注入的接口类型</typeparam>
public class Client<T>:ITimeProvider
where T:ITimeProvider
{
/// <summary>
/// 与设值方式相似的注入入口
/// </summary>
public T Provider { get; set; } /// <summary>
/// 类似传统接口注入的实现方式
/// </summary>
public DateTime CurrentDate
{
get { return Provider.CurrentDate; }
}
}
Unit Test
[TestMethod]
public void Test()
{
var clietn = new Client<ITimeProvider>()
{
Provider = (new Assembler().Create<ITimeProvider>())
}; //验证设置方式注入的内容
Assert.IsNotNull(clietn.Provider);
Assert.IsNotInstanceOfType(clietn.Provider, typeof(SystemTimeProvider)); //验证注入的接口是否可用
Assert.IsNotInstanceOfType(clietn.Provider.CurrentDate, typeof(DateTime)); //验证是否满足传统接口注入的要求
Assert.IsTrue(typeof(ITimeProvider).IsAssignableFrom(clietn.GetType()));
}
基于特性的注入方式(Attributer)
直观上,客户程序可能在使用上做出让步以适应变化,但这违背了依赖注入的初衷,即三个角色(客户对象、Assembler、抽象类型)之中两个不能变,如果在Assembler和客户类型选择,为了客户对象影响最小,我们只好在Assembler上下功夫,因为它的职责是负责组装。反过来讲,如果注入过程还需要修改客户程序,那我们就没有必要去“削足适履”地去用“依赖注入”了。
因此,为了能通过特性方式完成依赖注入,我们只好在Assembler上下功夫
(错误的实现情况)
class SystemTimeAttribute:Attribute,ITimeProvider{…}
[SystemTime]
class Client{…}
相信读者也发现了,这样做虽然把客户类型需要的ITimeProvider通过“贴标签”的方式告诉它了,但事实上又把客户程序与SystemTimeAttribute“绑”上了,他们紧密的耦合在一起了。参考上面的三个实现,当抽象类型与客户对象耦合的时候我们就要用Assembler解耦。
当特性方式出现类似情况时,我们写一个AtttibuteAssembler不就行了吗?
还不行,设计上要把Attribute设计成一个通道,出于扩展和通用性的考虑,它本身要协助AtttibuteAssembler完成ITimeProvider的装配,最好还可以同时装载其他抽象类型来修饰客户类型。
示例代码如下
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class DecoratorAttribute : Attribute
{
//实现客户类型实际需要的抽象类型的实体类型实例,即待注入客户类型的内容
public readonly object Injector;
readonly Type type; public DecoratorAttribute(Type type)
{
if (type == null) throw new ArgumentNullException("type");
this.type = type; Injector = (new Assembler()).Create(this.type);
} //客户类型需要的抽象对象类型
public Type Type { get { return this.type; } }
} public static class AttributeHelper
{
public static T Injector<T>(object target) where T : class
{
if (target == null) throw new ArgumentNullException("target");
return (T)(((DecoratorAttribute[])
target.GetType().GetCustomAttributes(typeof(DecoratorAttribute), false))
.Where(x => x.Type == typeof(T)).FirstOrDefault()
.Injector);
}
}
[Decorator(typeof(ITimeProvider))]
//应用Attribute,定义需要将ITimeProvider通过它注入
class Client
{
public int GetYear()
{
//与其他注入不同的是,这里使用ITimeProvider来自自己的Attribute
var porvider = AttributeHelper.Injector<ITimeProvider>(this);
return porvider.CurrentDate.Year;
}
}
Unit Test
[TestMethod]
public void Test1()
{
Assert.IsTrue(new Client().GetYear() > 0);
}
依赖注入(IOC)二的更多相关文章
- android使用篇(四) 注解依赖注入IOC实现绑定控件
在android使用篇(三) MVC模式中提到一个问题: 1) 视图层(View):一般採用XML文件进行界面的描写叙述,使用的时候能够很方便的引入,可是用xml编写了,又须要在Acitvity声明而 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...
- Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
本文梯子 本文3.0版本文章 更新 代码已上传Github+Gitee,文末有地址 零.今天完成的绿色部分 一.依赖注入的理解和思考 二.常见的IoC框架有哪些 1.Autofac+原生 2.三种注入 ...
- 我的NopCommerce之旅(7): 依赖注入(IOC/DI)
一.基础介绍 依赖注入,Dependency Injection,权威解释及说明请自己查阅资料. 这里简单说一下常见使用:在mvc的controller的构造方法中定义参数,如ICountryServ ...
- 大话DI依赖注入+IOC控制反转(二) 之 浅析.Net Core中的DI与IOC
转发时请注明原创作者及地址,否则追究责任.原创:alunchen 在上一篇文章中,我们聊了很多关于定义的方面,比较孤燥,下面我们结合.Net Core聊一下依赖注入&控制反转. 三种对象生 ...
- DI依赖注入/IOC控制反转
DI依赖注入# 啥都不说,直接上代码 <?php class UserController { private $user; function __construct(UserModel $us ...
- Unity 依赖注入之二
1. 构造子注入 1.1 构造子注入初级代码 container.RegisterType<IMyWork, MyWork>(new InjectionConstructor(new Bo ...
- 关于依赖注入IOC/DI的感想
之前一直不明白依赖注入有什么好处,甚至觉得它是鸡肋,现在想想,当时真是可笑. 这个想法正如同说接口是没有用处一样. 当整个项目非常庞大,各个方法之间的调用非常复杂,那么,可以想象一下,假设说没有任何的 ...
- Spring控制反转与依赖注入(IOC、DI)
IOC: 反转控制 Inverse Of Control DI:依赖注入 Dependency Injection 目的:完成程序的解耦合 解释:在应用系统的开发过程中,有spring负责对象的创 ...
- 轻松了解Spring中的控制反转和依赖注入(二)
紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...
随机推荐
- 嵌Ruby 2 《捆绑》
本章主要介绍 Ruby Object 与C++对象绑定 //====================================================================== ...
- CSS3+HTML5特效4 - 横向无缝滚动
先看例子 This is a test 1. This is a test 2. This is a test 3. This is a test 4. This is a test 5. This ...
- SQL2005性能分析一些细节功能你是否有用到?(三)
原文:SQL2005性能分析一些细节功能你是否有用到?(三) 继上篇: SQL2005性能分析一些细节功能你是否有用到?(二) 第一: SET STATISTICS PROFILE ON 当我们比较查 ...
- Socket 学习(三).2 udp 穿透 服务端 与 客户端 通讯
之前演示的 是 局域网通讯,也可以用作服务器之间的通讯,不能穿透. 想要穿透就要用 udp 了, 后续再讲解 udp 打洞 . 客户端: using System; using System.Wind ...
- JAVA Static方法与单例模式的理解
近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对s ...
- 最新发布树莓派2代Wi-Fi自动连接实战(适合初学者)
话说天地会珠海分舵在上几天才刚给大家分享了个海外资讯说树莓派2已经发布且Windows10加盟之类的资讯,具体请查看<海外优秀资讯抢先看8 - Windows 10 for Raspberry ...
- linux监控命令全覆盖(图文说明)
1.1 top 1.1.1 命令说明 Top 命令能够实时监控系统的运行状态,并且可以按照cpu.内存和执行时间进行排序 1.1.2 参数说明 命令行启动参数: 用法: top -hv | -bcis ...
- selenium2入门 定位 窗体切换等等 (二)
定位用的html素材有两个 demo.html <html> <head> <title>UI Automation Testing</title> & ...
- ASP.NET WebForm路由模拟
一.ASP.NET MVC 路由(一)--- ASP.NET WebForm路由模拟 2014-11-08 11:49 by 郝喜路, 232 阅读, 0 评论, 收藏, 编辑 ASP.NET Web ...
- 分享12款经典时尚的HTML5应用
分享伟大,呵呵.今天给大家分享一下收集的12个HTML5小特效. 我整理一下源码,给大家打包一下,我博客园上传文件大小有限,传不了了. 需要的请留下邮箱就行了,觉得好的话,不要忘了点赞哦~ 1.CSS ...