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应用中访 ...
随机推荐
- 【应用服务 App Service】解决无法从Azure门户SSH登录问题
问题描述 中国区的Azure App Service(应用服务)已经支持创建Docker并选择Linux环境.在使用中,我们可以继续通过kudu站点的方式登录查看站点的一些日志及部署文件.它的登录方式 ...
- 公平lock和非公平lock的区别
可以看到区别在于,在lock时和tryAquire时,非公平锁不会去管队列中有没有线程在排队,直接尝试去获取锁,失败之后就和公平锁一样,乖乖去排队. 也就是说发生竞争的场景在于,尚未入队的线程之间和刚 ...
- Kafka入门之producer
一些重要的参数: 1.acks指定了在给producer发送响应前,leader broker必须要确保已成功写入该消息的副本数.当前acks有3个取值,0,1,和all 2.buffer.memor ...
- CountDownLatch、CyclicBarrier、Semaphore、Exchanger 的详细解析
本文主要介绍和对比我们常用的几种并发工具类,主要涉及 CountDownLatch . CyclicBarrier . Semaphore . Exchanger 相关的内容,如果对多线程相关内容不熟 ...
- Alpha冲刺-第三次冲刺笔记
Alpha冲刺-冲刺笔记 这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE2 这个作业要求在哪里 https://edu.cnblogs. ...
- MySQL(13)---MYSQL主从复制原理
MYSQL主从复制原理 最近在做项目的时候,因为部署了 MYSQL主从复制 所以在这里记录下整个过程.这里一共会分两篇博客来写: 1.Mysql主从复制原理 2.docker部署Mysql主从复制实战 ...
- this大全,还有谁??????!!!!!!!
this在函数调用时创建,一般的对象没有this,全局window可以理解为一个函数,他有一个全局this JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系. 函数里thi ...
- 【入门】ZooKeeper 相关概念总结
1. 前言 相信大家对 ZooKeeper 应该不算陌生.但是你真的了解 ZooKeeper 到底有啥用不?如果别人/面试官让你给他讲讲对于 ZooKeeper 的认识,你能回答到什么地步呢? 拿我自 ...
- 记一次MySQL出现Waiting for table metadata lock的原因、排查过程与解决方法
任务背景:将sql文件通过shell直接导入到mysql中执行(还原) bug表现:导入后java项目卡死 过程: 1.网上乱搜一通,无意间看到一篇文章,这篇文章说明了如何开启mysql的genera ...
- moviepy AudioClip的max_volume方法报错ValueError: operands could not be broadcast together with shapes(2,)
☞ ░ 前往老猿Python博文目录 ░ 在<moviepy音视频剪辑:AudioClip的max_volume方法报TypeError: bad operand type for abs(): ...