三、服务解析(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 : 非\ ...
随机推荐
- 多线程、多任务管理 简单demo
需求:假设多个任务需要执行,每个任务不是一时半会能完成(需要能看到中间执行状况): 多个任务 根据条件不同 可能需要不同的处理 分析: 多线程并发执行多任务: 对任务进行管理,追踪中间执行状态: 运用 ...
- 关于sqfa
有的时候定义状态,下次来到这个状态的时候,不应该就否决掉下次,因为下次的权值可能比这次更优..
- HIVE快速入门
(一)简单入门 1.创建一个表 create table if not exists ljh_emp( name string, salary float, gender string) commen ...
- 3月25日 javascript练习
1.找出100以内带7的数字 2.求1!+2!+3!+......+n!的和
- PHP程序员衰老后的下场
长期从事编程活动的程序员都期望在50多岁时能爬到一个足够高的职位,或者能顺利的退休. 但我在这里讨论的可能是一个你还没有想过的问题:如果到那时你失业了呢? 50多岁时你的职业仕途会成为一个问题.如果你 ...
- Ubuntu 14.04 标题栏实时显示上下行网速、CPU及内存使用情况
首先当然是用wget下载indicator-sysmonitor,终端执行命令:wget -c https://launchpad.net/indicator-sysmonitor/trunk/4.0 ...
- QuickTime 专业版 pro 注册码
打开QuickTime Player下拉编辑菜单--选偏好设置--注册 Name: Dawn M Fredette Key: 4UJ2-5NLF-HFFA-9JW3-X2KV 重新启动 QuickTi ...
- Codeforces 335B Palindrome
http://codeforces.com/contest/335/problem/B 题意: 给定一个长度不超过5*10^4的只包含小写字母的字符串,要求你求它的回文子序列,如果存在长度为100的 ...
- Android实现摇晃手机的监听
摘自:http://blog.csdn.net/xwren362922604/article/details/8515343 监听摇晃手机的类: /** * @author renxinwei ...
- Entity framework - start
http://blogs.msdn.com/b/adonet/archive/2010/07/19/absolue-beginners-guide-to-entity-framework.aspx?R ...