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应用中访 ...
随机推荐
- P6631 [ZJOI2020] 序列
可以将问题用形象的方式来表述.给定一排点,第 \(i\) 个点有它需要的覆盖次数 \(a_i\).有两种线段,一种能覆盖连续的一些点,称其为连续线段:另一种能覆盖相邻间隔为 \(1\) 的一些点,称其 ...
- Codeforces Round #672 (Div. 2) B. Rock and Lever题解(思维+位运算)
题目链接 题目大意 给你一个长为n(n<=1e5)的数组,让你求有多少对a[i]和a[j] (i!=j)满足a[i]&a[j]>a[i]^a[j] 题目思路 这些有关位运算的题目肯 ...
- java数组作为函数返回值
1 //将一个二维数组行和列元素互换.存到另一个二维数组 2 package test; 3 4 public class test1_8 { 5 public static int[][] huhu ...
- vue获取微博授权URL
1.在Vue**页面加载时动态发送请求获取微博授权url 1.1 在 components\common\lab_header.vue 中写oauth动态获取微 博授权URL // 获取微博登录地址 ...
- Mysql命令、常用函数
一.sql命令行 查看数据库 show database : 选择使用的数据库 use 数据库名 : 查看表 show tables ; 查询表 select * from 表名 高版本my ...
- CentOS SSH安全和配置无密码登录
CentOS ssh默认监听端口 22端口,允许root用户ssh登录.server投入生产后很有必要更改默认ssh监听端口和禁止root登录. 步骤1:确认安装有ssh包 [appuser@su17 ...
- Window .NetCore Nginx
1.首先去官网下载Nginx 官网地址:http://nginx.org/en/download.html 2.下载好之后,我的文件是放在D:\InstallFiles\Nginx\nginx-1.1 ...
- IEEE754标准浮点数表示与舍入
原文地址:https://blog.fanscore.cn/p/26/ 友情提示:本文排版不太好,但内容简单,请耐心观看,总会搞懂的. 1. 定点数 对于一个无符号二进制小数,例如101.111,如果 ...
- 【2020.11.28提高组模拟】T1染色(color)
[2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...
- Spring Boot 实现看门狗功能 (调用 Shell 脚本)
需要实现看门狗功能,定时检测另外一个程序是否在运行,使用 crontab 仅可以实现检测程序是否正在运行,无法做到扩展,如:手动重启.程序升级(如果只需要实现自动升级功能可以使用 inotify)等功 ...