依赖注入(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的工作机制,使我们更加深刻的理解其中的工作. 类 ...
随机推荐
- 随想录(从apple的swift语言说起)
[ 声明:版权全部,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 喜欢apple的程序猿朋友对wwdc肯定不会陌生.本次wwdc上最大的一个亮点之中的一个就是s ...
- 拷贝构造函数,深拷贝,大约delete和default相关业务,explicit,给定初始类,构造函数和析构函数,成员函数和内联函数,关于记忆储存,默认参数,静态功能和正常功能,const功能,朋友
1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.另外一种初始化的方式是直接在构造方法里面实现初始化. 案比例如以 ...
- 透过【百度地图API】分析双闭包问题
原文:透过[百度地图API]分析双闭包问题 摘要: 有位API爱好者问到,昨天的教程里为什么不使用for循环?他使用for循环后,也发现代码无效.这是什么原因? ------------------- ...
- RPC和RMI的区别(Difference Between RPC and RMI)
RPC和RMI的区别(Difference Between RPC and RMI) RPC vs RMI RPC (Remote Procedure Call) and RMI (Remote Me ...
- signalR例子
不用找了,比较全的signalR例子已经为你准备好了. 这几天想着将一个winform的工具上线到web上,因为对时时性的要求比较高,找朋友咨询了一下推荐了SignlarR 框架,比较强大.昨天才 ...
- Gaea是支持跨平台具有高并发、高性能、高可靠性,并提供异步、多协议、事件驱动的中间层服务框架
Gaea是支持跨平台具有高并发.高性能.高可靠性,并提供异步.多协议.事件驱动的中间层服务框架 Gaea:58同城开源的中间层服务框架 https://github.com/58code/Gaea 中 ...
- 分享一个SQLSERVER脚本
原文:分享一个SQLSERVER脚本 分享一个SQLSERVER脚本 很多时候我们都需要计算数据库中各个表的数据量很每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tablespac ...
- java之集合框架使用细节及常用方法
集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定. 就使用集合容器进行存储. 集合特点: 1,用于存储对象的容器. 2,集合的长度是可变的. 3,集合中不可以存储基本 ...
- 为网上流行论点“UIAutomator不能通过中文文本查找控件”正名
1. 问题描述和起因 相信大家学习UIAutomator一开始的时候必然会看过一下这篇文章. Android自动化测试(UiAutomator)简要介绍 因为你在百度输入UIAutomator搜索的时 ...
- ural1519插头DP
1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that V ...