三、服务解析(Resolving Services)
当你完成组件注册,并将组件暴露为适当的服务后你就可以通过容器或者容器的子生命周期域来解析服务(After you have your components registered with appropriate services exposed, you can resolve services from the built container and child lifetime scopes)。你可以通过Resolve()方法来解析服务。
var builder = new ContainerBuilder();
builder.RegisterType<MyComponent>.As<IService>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var service = scope.Resolve<IService>();
}
你可能已经注意到例子中是通过容器的子生命周期域对服务进行解析而不是直接使用容器(container)来接服务的——你也应该以这样的方式来解析服务。
虽然也可以直接使用容器(container)来解析服务,但如果你这样做可能导致应用程序内存泄漏。所以建议你总是尽可能的在自生命周期域中解析服务,这样autofac能够帮助你妥善的处理对象销毁以及垃圾回收工作。你将在今后的章节中了解到更详细的内容。
解析服务时,autofac将自动的连接服务的整个依赖层次,并且自动构件服务所需要的依赖项。当你的程序中存在循环依赖项或者依赖项缺失,那么程序将会抛出DependencyResolutionException异常。
假设你有一个服务,但不能确定它是否已经注册到容器当中,你可以尝试使用ResolveOptional() 或者TryResolve()方法进行条件解析:
//如果已经注册了IService服务,那么它将被正确的解析,
//如果没有对IService服务进行注册,那么该方法将返回null
var service = scope.ResolveOptional<IService>(); //如果IProvider进行了注册,那么provider将获得对象,
//如果IProvider没有注册,那么你可以进行其他操作
IProvider provider = null
if(scope.TryResolve<IProvider>(out provider))
{
//服务被成功解析
}
3.1、为解析传递参数(Passing Parameters to Resolve)
当你解析服务的时候,可能会需要额外的参数才能完成解析。(作为代替,如果在组件注册时就能明确该参数的值,你也可以直接在注册时提供该参数)。
Resolve()方法用可变参数列表的方式接受参数。委托工厂(delegate factories)和Function<T>隐式关系类型(Function<T> implicit relationship type)也可以在解析时传递参数。(这段不是很明确,贴出原文等待高人指导:The Resolve() methods accept the same parameter types available at registration time using a variable-length argument list. Alternatively, delegate factories and the Func<T> implicit relationship type also allow ways to pass parameters during resolution.)
3.1.1、可用参数类型(Available Parameter Types)
autofac提供了几种不同的参数匹配策略:
- NamedParameter——通过参数名称进行匹配
- TypedParameter——通过参数类型进行匹配
- ResolvedParameter——灵活的参数匹配
NamedParameter和TypedParameter只能够提供常量值
ResolvedParameter提供的值可以从容器中动态的检索,比如通过名字来解析一个服务。(ResolvedParameter can be used as a way to supply values dynamically retrieved from the container, e.g. by resolving a service by name.)
3.1.2、参数与反射组件(Parameters with Reflection Components)
使用基于反射进行创建的组件时,组件的构造函数可能会需要一个只有在运行时才能确定的值作为参数。你可向Resolve()方法传递一个parameter参数(个人理解这个parameter指代的是NamedParameter、TypedParameter、ResolveParameter)从而帮助容器创建该组件。
如下的ConfigurationReader类,需要一个配置节(configuration section)名称作为参数:
public class ConfigReader : IConfigReader
{
public ConfigReader(string configurationSectionName)
{
//保存配置节名称
} //基于configurationSectionName读取配置
}
你可以按下面的方式为Resolve()传递一个parameter参数
var reader = container.Resolve<ConfigReader>(new NamedParameter("configurationSectionName", "sectionName"));
上面的例子中NamedParameter将按照名称(configurationSectionName)将值(sectionName)映射到ConfigReader的构造函数。
如果你的组件有多个参数,同样可以使用Parameter参数传递给Resolve()方法:
var service = scope.Resolve<AnotherService>(
new NamedParameter("id", "service-identifier"),
new TypedParameter(typeof(Guid), Guid.NewGuid()),
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ILog) && pi.Name == "logger",
(pi, ctx) => LogManager.GetLogger("service")));
3.1.3、参数与Lambda表达式组件
使用Lambda表达式注册的组件,在使用Resolve()方法传递parameter参数时需要在注册组件的Lambda表达式中增加一些额外的处理。
在组件注册的表达式中,可以通过改变委托签名来使用传入的参数。之前使用的委托签名只有一个IComponentContext类型参数,而新的委托签名具有一个IComponentContext类型参数和一个IEnumerable<Parameter>类型的参数:
//注册是使用具有两个参数的委托
//c=IComponentContext,当前组件上下文,用于从容器中动态解析依赖
//p=IEnumerable<Parameter>,传入的参数集合
builder.Register((c, p) =>new ConfigReader(p.Named<string>("configSectionName"))).As<IConfigReader>();
现在解析IConfigReader时,你的lambda表达是就能够使用传入的参数了:
IConfigReader reader = container.Resolve<IConfigReader>(new NamedParameter("configSectionName", "sectionName"));
3.1.4、非显示调用Resolve传参(Passing Parameters Without Explicitly Calling Resolve)
autofac支持两种特性,允许自动生成服务工厂,该服务工厂可以在解析组件时使用强类型参数列表。
- Delegate Factories允许你定义工厂委托方法
- Func<T>隐式关心类型(Func<T> implicit relationship type)提供自动生成的工厂方法(The Func<T> implicit relationship type can provide an automatically-generated factory function.)
3.2、隐式关系类型(Implicit Relationship Types)
autofac能够自动完成一些特定类型的解析工作,这些特定类型的组件和服务有着间接的关系,要使用这些关系,你只需要正常的注册你的组件,但是在调用Resolve()方法时,稍稍改变传入的参数或参数类型以此表明你要使用它们之间的间接关系。(这段话的意思我是理解了,但好难用中文来表述啊!我还是贴出原文吧。Autofac supports automatically resolving particular types implicitly to support special relationships between components and services. To take advantage of these relationships, simply register your components as normal, but change the constructor parameter in the consuming component or the type being resolved in the Resolve() call so it takes in the specified relationship type.要是看原文还不理解,也没关系,接着往下看一定会明白,而且会发现这段是作者在语言描述上卖了萌,哈哈)
比如说,Autofac进行构造函数注入,而这个构造函数要求提供一个IEnumerable<ITask>类型的参数,autofac可能会找不到IEnumerable<ITask>匹配的组件,这种情况下它会去寻找所有ITask相对应的组件,并使用这些组件进行注入。(没看懂也别担心,下面还会有例子进行说明的)
3.2.1、支持的关系类型(Supported Relationship Types)
下表总结了.net中,autofac支持的(隐式)关系类型,以下的每种类型都会有更详细的描述和用
关系 | 类型 | 含义 |
A需要B(A need B) |
B | 直接依赖(Direct Dependency) |
将来的某一点A需要B(A need B at some point in the future) |
Lazy<B> | 延迟实例化(Delayed Instantiation) |
A需要B直到将来某一点(A need B until some point int future) |
Owned<B> | 控制生命周期(Controlled Lifetime) |
A需要创建B的实例(A need to create instances of B) |
Func<B> | 动态实例化(Dynamic Instantiation) |
A为B提供类型为X和Y的参数(A provides paramteres of types X and Y to B) |
Func<X,Y,B> |
参数化的实例化(Parameterized Instantiation) |
A需要所有B(A need all kinds of B) |
IEnumerable<B>, IList<B>, |
枚举(Enumeration) |
A needs to know X about B |
Meta<B> and Meta<B,X> | Metadata Interrogation |
A需要基于X对B进行选择 |
IIndex<X,B> | Keyed Service Lookup |
明天继续...
PS:本系列博客是对autofac英文资料的翻译,主要目的是为了提高自己英文阅读能力,同时能够帮助有需要的人,原文地址http://autofac.readthedocs.org/en/latest/getting-started/index.html。3.2节真心难翻译!
三、服务解析(Resolving Services)的更多相关文章
- WebSocket安卓客户端实现详解(三)–服务端主动通知
WebSocket安卓客户端实现详解(三)–服务端主动通知 本篇依旧是接着上一篇继续扩展,还没看过之前博客的小伙伴,这里附上前几篇地址 WebSocket安卓客户端实现详解(一)–连接建立与重连 We ...
- iOS系统声音服务(System Sound Services)
系统声音服务(System Sound Services)提供了一个接口,用于播放不超过30秒的声音.它支持的文件格式有限,具体地说只有CAF.AIF和使用PCM或IMA/ADPCM数据的WAV文件. ...
- [转]访问 OData 服务 (WCF Data Services)
本文转自:http://msdn.microsoft.com/zh-SG/library/dd728283(v=vs.103) WCF 数据服务 支持开放式数据协议 (OData) 将数据作为包含可通 ...
- 网络安全服务(Network Security Services, NSS
网络安全服务(Network Security Services, NSS)是一套为网络安全服务而设计的库 支持支持安全的客户端和 服务器应用程序.使用NSS构建的应用程序可以支持SSL v2 和v3 ...
- JSON的三种解析方式
一.什么是JSON? JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度. JSON就是一串字符串 只不过元素会使用特定 ...
- Android平台中实现对XML的三种解析方式
本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...
- 【开源.NET】轻量级内容管理框架Grissom.CMS(第三篇解析配置文件和数据以转换成 sql)
该篇是 Grissom.CMS 框架系列文章的第三篇, 主要介绍框架用到的核心库 EasyJsonToSql, 把标准的配置文件和数据结构解析成可执行的 sql. 该框架能实现自动化增删改查得益于 E ...
- Qt中三种解析xml的方式
在下面的随笔中,我会根据xml的结构,给出Qt中解析这个xml的三种方式的代码.虽然,这个代码时通过调用Qt的函数实现的,但是,很多开源的C++解析xml的库,甚至很多其他语言解析xml的库,都和下面 ...
- 【Oracle学习笔记-3】关于Oracle 10g中各种服务解析
[原创]关于oracle 10g中各种服务解析 (2014/10/16 8:39:40) 时间:2014-10-16 8-58-30 作者:ssslinppp 1. 当首次安装oracle 1 ...
- python爬虫之数据的三种解析方式
一.正则解析 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线.中文 \W : 非\ ...
随机推荐
- js_day1
1)在js写<br>是要"<br>" 2)一些函数a.length,math.random()(1~0),math.floor()(2.3,2.5--> ...
- 求解:C#.Net 远程方法调用失败 (Exception from HRESULT: 0x800706BE)
服务器:Windows Server2003 sp2服务器 客户端:XP SP3 内容:C#Winform客户端调用服务器的Excel模板生成报表的时候,生成失败,抛出的异常如下: TargetInv ...
- magent——memcached缓存代理服务器
memcached分布式缓存 我们使用PHP连接多台memcached服务器,做分布式缓存,实现如下: $memcache = new Memcache; $memcache->addServe ...
- JavaScript文本框统计字数
<html> <head> <title>enter</title> <script language="javascript" ...
- tensorflow 使用
1.linux 安装tensorflow ubuntu中安装:link 用pip安装的过程中,可能出现网络链接的问题,尝试多次链接,直到成功!!! python -V sudo apt-get ins ...
- 基于Http原理实现Android的图片上传和表单提交
版权声明:本文由张坤 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/794875001483009140 来源:腾云阁 ...
- QT 串口通信 数据16进制发送
在QT中进行串口通信时,很多情况要用到发送16进制的数据.从网上找来了一段代码测试能用: static QByteArray QString2Hex(QString str) { QByteArray ...
- 从现在开始使用nodejs开发的几点答疑
1.为什么要开始用nodejs, 而不是php 理由有三点: 因为我是前端程序员出身,nodejs都是用javascript写的,这样相当于前端和后端都使用javascript,开发更加有效率.当然很 ...
- PYTHON线程知识再研习A
前段时间看完LINUX的线程,同步,信息号之类的知识之后,再在理解PYTHON线程感觉又不一样了. 作一些测试吧. thread:模块提供了基本的线程和锁的支持 threading:提供了更高级别,功 ...
- Sessions, Window Stations and Desktops(GetDesktopWindow函数得到的桌面句柄, 是Csrss.exe创建的一个窗口)
由于不是搞安全的,对这块的东西一直不是很清楚,今天特意整理下. 总的来说,他们的关系如下: 我们知道Windows是支持多用户的,Session可以理解为每个用户登录,比如当前登录和远程登陆.Wind ...