Autofac官方文档翻译--二、解析服务--2隐式关系类型
Autofac 隐式关系类型
1、支持的关系类型
关系 | 类型 | 含义 |
A needs B | B | Direct Dependency(直接依赖关系) |
A needs B at some point in the future | Lazy<B> | Delayed Instantiation(延迟实例化) |
A needs B until some point in the future | Owned<B> | Controlled Lifetime(控制生命周期) |
A needs to create instances of B | Func<B> | Dynamic Instantiation(动态实例) |
A provides parameters of types X and Y to B | Func<X,Y,B> |
Parameterized Instantiation(参数化实例化) |
A needs all the kinds of B |
IEnumerable<B>, IList<B>, ICollection<B> |
Enumeration(枚举) |
A needs to know X about B | Meta<B> and Meta<B,X> | Metadata Interrogation |
A needs to choose B based on X | IIndex<X,B> | Keyed Service Lookup(键控服务查找) |
1.1Direct Dependency (B)--直接依赖
public class A
{
public A(B dependency) { ... }
}
var builder = new ContainerBuilder();
builder.RegisterType<A>();
builder.RegisterType<B>();
var container = builder.Build(); using(var scope = container.BeginLifetimeScope())
{
// B 自动注入到 A 中
var a = scope.Resolve<A>();
}
1.2Delayed Instantiation (Lazy<B>)--惰性依赖
public class A
{
Lazy<B> _b; public A(Lazy<B> b) { _b = b } public void M()
{
// 在第一次调用 M() 方法时,创建组件 B
_b.Value.DoSomething();
}
}
1.3 Controlled Lifetime (Owned<B>)
public class A
{
Owned<B> _b; public A(Owned<B> b) { _b = b; } public void M()
{
// _b is used for some task
_b.Value.DoSomething(); // 这里 _b 不再需要,所以,释放他
_b.Dispose();
}
}
在内部,Autofac创建一个微小的lifetime scope,其中对B服务解析,且当你调用它的Dispose()时,这个lifetime scope 将被处理。这也就意味着,释放B也将释放它的依赖关系,除非这些依赖是共享的。
var builder = new ContainerBuilder();
builder.RegisterType<A>().InstancePerLifetimeScope();
builder.RegisterType<B>().InstancePerLifetimeScope();
var container = builder.Build(); using(var scope = container.BeginLifetimeScope())
{
// 这里解析一个使用了 InstancePerLifetimeScope() 的 类型 B ;
var b1 = scope.Resolve<B>();
b1.DoSomething(); // 这个和上面的 b1 一样。
var b2 = scope.Resolve<B>();
b2.DoSomething(); // 在类型 A 中使用的类型 B 和其他地方的 B 不是同一个
var a = scope.Resolve<A>();
a.M();
}
设计就是这样的,因为你不想让一个组件处理 B 下的一切事情。然而,如果你不知道,它可能会导致一些混乱。
1.4 Dynamic Instantiation (Func<B>)--动态实例化
public class A
{
Func<B> _b; public A(Func<B> b) { _b = b; } public void M()
{
var b = _b();
b.DoSomething();
}
}
1.5Parameterized Instantiation (Func<X, Y, B>)
public class A
{
Func<int, string, B> _b; public A(Func<int, string, B> b) { _b = b } public void M()
{
var b = _b(42, "http://hel.owr.ld");
b.DoSomething();
}
}
在内部,Autofac将它们视为类型的参数。这也就意味着,自动生成函数工厂,不能在输入参数列表中有重复的类型。例如,你有这样一个类型:
public class DuplicateTypes
{
public DuplicateTypes(int a, int b, string c)
{
// ...
}
}
var func = scope.Resolve<Func<int, int, string, DuplicateTypes>>(); // Throws a DependencyResolutionException:
var obj = func(1, 2, "three");
在一个松耦合的场景下,其中的参数需与类型相匹配,你不了解特定对象的构造函数的参数顺序。如果你需要做这样的事情,你应该使用自定义的委托类型来代替:
public delegate DuplicateTypes FactoryDelegate(int a, int b, string c);
RegisterGeneratedFactory()注册委托
:builder.RegisterType<DuplicateTypes>();
builder.RegisterGeneratedFactory<FactoryDelegate>(new TypedService(typeof(DuplicateTypes)));
现在这个函数将工作:
var func = scope.Resolve<FactoryDelegate>();
var obj = func(1, 2, "three");
你有另一种方式,就是使用使用委托工厂。
var func = container.Resolve<Func<int, string, DuplicateTypes>>(); // This works and is the same as calling
// new DuplicateTypes(1, 1, "three")
var obj = func(1, "three");
使用这种关系类型且使用委托工厂时推荐使用Lifetime scopes.如果您注册一个对象为InstancePerDependency(),并多次调用Func<X,Y,B>
,每次你将得到一个新实例。但是,如果你注册一个对象为SingleInstance(),并调用Func<X,Y,B>
多次解析对象,你每次都会得到同一个对象实例即使你传递不同的参数。仅仅传递不同的参数不能打破lifetime scope。
1.6 Enumeration (IEnumerable<B>, IList<B>, ICollection<B>)
public interface IMessageHandler
{
void HandleMessage(Message m);
}
此外,你有一个用户的依赖关系,你需要有多个注册和用户需要的所有注册的依赖关系:
public class MessageProcessor
{
private IEnumerable<IMessageHandler> _handlers; public MessageProcessor(IEnumerable<IMessageHandler> handlers)
{
this._handlers = handlers;
} public void ProcessMessage(Message m)
{
foreach(var handler in this._handlers)
{
handler.HandleMessage(m);
}
}
}
您可以使用隐枚举关系类型很容易地做到这一点。只需注册所有的依赖和用户,并且当你解析用户,它所匹配的所有依赖将被解析为一个枚举:
var builder = new ContainerBuilder();
builder.RegisterType<FirstHandler>().As<IMessageHandler>();
builder.RegisterType<SecondHandler>().As<IMessageHandler>();
builder.RegisterType<ThirdHandler>().As<IMessageHandler>();
builder.RegisterType<MessageProcessor>();
var container = builder.Build(); using(var scope = container.BeginLifetimeScope())
{
// When processor is resolved, it'll have all of the
// registered handlers passed in to the constructor.
var processor = scope.Resolve<MessageProcessor>();
processor.ProcessMessage(m);
}
如果没有匹配的项目在容器中注册,枚举将返回一个空集。也就是说,使用上面的例子,如果你没有注册任何IMessageHandler 实现时,它将中断:
// This throws an exception - none are registered!
scope.Resolve<IMessageHandler>();
// This returns an empty list, NOT an exception:
scope.Resolve<IEnumerable<IMessageHandler>>();
你可能认为,如果你使用这种关系注入东西,你会得到一个空值。相反,你会得到一个空列表。
1.7Metadata Interrogation (Meta<B>, Meta<B, X>)
public class A
{
Meta<B> _b; public A(Meta<B> b) { _b = b; } public void M()
{
if (_b.Metadata["SomeValue"] == "yes")
{
_b.Value.DoSomething();
}
}
}
你也可以使用 strongly-typed 元数据, 通过在 Meta<B,X>
关系中指定元数据类型:
public class A
{
Meta<B, BMetadata> _b; public A(Meta<B, BMetadata> b) { _b = b; } public void M()
{
if (_b.Metadata.SomeValue == "yes")
{
_b.Value.DoSomething();
}
}
}
如果你有一个惰性依赖也需要元数据,你可以使用Lazy<B,M> 代替Meta<Lazy<B>, M>
1.8 Keyed Service Lookup (IIndex<X, B>)
var builder = new ContainerBuilder();
builder.RegisterType<DerivedB>().Keyed<B>("first");
builder.RegisterType<AnotherDerivedB>().Keyed<B>("second");
builder.RegisterType<A>();
var container = builder.Build();
然后使用IIndex<X,B>得到一个keyd服务字典:
public class A
{
IIndex<string, B> _b; public A(IIndex<string, B> b) { _b = b; } public void M()
{
var b = this._b["first"];
b.DoSomething();
}
}
2、组成关系类型
IEnumerable<Func<Owned<ITask>>>
正确的解释为:
- All implementations, of
- Factories, that return
- Lifetime-controlled
- ITask services
3、关系类型和容器独立
Func<Owned<ITask>>
的AutofacTaskFactory实现。Autofac官方文档翻译--二、解析服务--2隐式关系类型的更多相关文章
- Autofac官方文档翻译--二、解析服务--1解析参数传递
Autofac 传递解析参数 注册组件公开相应的服务之后,你可以从container构造器和子lifetime scopes 中解析服务.使用Resolve()方法来实现: var builder = ...
- Autofac官方文档翻译--一、注册组件--1注册概念
官方文档:http://docs.autofac.org/en/latest/register/registration.html 一.注册概念 使用Autofac 注册组件,通过创建一个Contai ...
- 《前端之路》之二:数据类型转换 && 隐式转换 || 显式转换
目录 02:数据类型转换 && 隐式转换 || 显式转换 02:数据类型转换 && 隐式转换 || 显式转换 在上一个章节中,我们介绍了 JavaScript 的基本的 ...
- 初步swift语言学习笔记2(可选类型?和隐式可选类型!)
作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/28904115 转载请注明出处 假设认为文章对你有所帮助.请通过留言 ...
- Atitit.变量的定义 获取 储存 物理结构 基本类型简化 隐式转换 类型推导 与底层原理 attilaxDSL
Atitit.变量的定义 获取 储存 物理结构 基本类型简化 隐式转换 类型推导 与底层原理 attilaxDSL 1.1. $ 美元字符, php 黑头1 1.2. 默认变量的范围和声明:1 1.3 ...
- Autofac官方文档翻译--一、注册组件--2传递注册参数
官方文档:http://docs.autofac.org/en/latest/register/parameters.html 二.Autofac 传递注册参数 当你注册组件时能够提供一组参数,可以在 ...
- C++隐式类类型转化
隐式类类型转换:可以用 单个形参来调用 的构造函数定义了从 形参类型 到 该类类型 的一个隐式转换 class Person { public: Person(): mName()name, mAge ...
- Orchard官方文档翻译(二) 安装 Orchard
原文地址:http://docs.orchardproject.net/Documentation/Installing-Orchard 想要查看文档目录请用力点击这里 最近想要学习了解orchard ...
- android菜鸟学习笔记25----与服务器端交互(二)解析服务端返回的json数据及使用一个开源组件请求服务端数据
补充:关于PHP服务端可能出现的问题: 如果你刚好也像我一样,用php实现的服务端程序,采用的是apache服务器,那么虚拟主机的配置可能会影响到android应用的调试!! 在android应用中访 ...
随机推荐
- Mockito 结合 Springboot 进行应用测试
Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试:Spring Boot可以跟BDD(Behavier Driven ...
- C语言讲义——内联函数
如果一些函数被频繁调用,不断地有函数入栈(Stack),会造成栈空间的大量消耗. 对应这种问题,可以使用内联函数(inline). 编译器会将内联函数的代码整段插入到调用的位置. #include & ...
- 考研数学数一公式整理(微积分&线性代数&概率统计)
主要根据李永乐老师的线性代数讲义.全书和汤家凤老师的高数讲义整理的. 用于记背数学需要背的公式和步骤,概念.定义.公式多,方法步骤少(毕竟太庞杂了). 本来是自用,但还是分享一下,希望有补充指正! 链 ...
- redis 客户端
输入缓冲区: 客户端状态的输入缓冲区用于保存客户端发送的命令请求: typedef struct redisClient{ //... sds querybuf; //... }redisClient ...
- python下载三方库源地址修改
临时使用 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 默认使用 windows系统使用cmd快速设置 pi ...
- 【佛山市选2013】JZOJ2020年8月7日提高组T2 树环转换
[佛山市选2013]JZOJ2020年8月7日提高组T2 树环转换 题目 描述 给定一棵N个节点的树,去掉这棵树的一条边需要消耗值1,为这个图的两个点加上一条边也需要消耗值1.树的节点编号从1开始.在 ...
- 基于CFSSL工具创建CA证书,服务端证书,客户端证书
背景描述 在局域网中部署组件时,想要通过证书来实现身份的认证,确保通信的安全性,可以通过cfssl工具来进行CA证书,服务端证书,客户端证书的创建. 目录 背景描述 部署cfssl工具 下载,上传cf ...
- buuctf-web-[极客大挑战 2019]BuyFlag 1
打开网页,然后发现menu中有个buyflag的连接,点进去 如果你想买这个flag ,你必须是来自CUIT的一名学生,还必须回答正确的密码.简单了解,我们查看源码,发现思路 POST方式传入两个参数 ...
- Python中判断字符串是否为数字的三个方法isdecimal 、isdigit、isnumeric的差别
isdecimal .isdigit.isnumeric这三个字符串方法都用于判断字符串是否为数字,为什么用三个方法呢?他们的差别是什么内? isdecimal:是否为十进制数字符,包括Unicode ...
- PyQt学习随笔:重写setData方法截获Model/View中视图数据项编辑的注意事项
根据<PyQt学习随笔:Model/View中视图数据项编辑变动实时获取变动数据的方法>可以重写从PyQt的Model类继承的setData方法来实时截获View中对数据的更改,但需要注意 ...