IoC容器Autofac正篇之类型关联(服务暴露)(八)
类型关联
类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例)。
一.As关联
我们在进行手动关联时,基本都是使用As进行关联的.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class Program{ static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<Class1>().As<IInterface>(); var container = builder.Build(); IInterface inter = container.Resolve<IInterface>(); Console.WriteLine(inter.Id); Console.Write("Press any key to continue..."); Console.ReadKey(); }}interface IInterface{ Guid Id { get; }}class Class1 : IInterface{ private Guid _id; public Guid Id { get { return _id; } }} |
从代码中可以看到,我们直接在类型注册后加了一句As<…>(),然后在使用Resolve时也是用的As的类型。
之前是直接RegisterType注册的类型是Class1,Resolve时也是直接用Class1。
而现在注册的虽然还是Class1,但是获取时却是用IInterface且最后获取到的实例类型是Class1。
这样看有点绕,但我们可以理解为注册了IInterface,但是为IInterface指定了实现。好处在于我们如果希望更改IInterface的实现,只需要修改注册的代码,而不需要修改获取处以及后续使用IInterface实例的代码。
多关联 一个类可能实现多个接口,如果我们希望Resolve多个接口时获取到的都是那个类型,应该怎么做呢?如果希望多个接口或类型都与同一个类型进行关联,我们可以直接再表达式后面继续As:builder.RegisterType<C1>().As<I1>().As<I2>().As<I3>,如此,Resolve<I1>、Resolve<I2>、Resolve<I3>获取到的都是C1类型实例。
二.自关联AsSelf
不使用As时,RegisterType注册的是什么类型,Resolve就使用什么类型获取,但使用As后就只能使用As的类型进行Resolve。比如前面的例子中,只能够Resolve<IInterface>,而不能Resolve<Class1>,否则抛出异常。但如想在Resolve<Class1>时能够获取到Class1而不抛出异常,应该怎么办呢?
|
1
2
3
|
// 这两句代码效果相同builder.RegisterType<Class1>().As<IInterface>().As<Class1>();builder.RegisterType<Class1>().As<IInterface>().AsSelf(); |
三 批量关联AsImplementedInerfaces
AsImplementedInterfaces也就是直接与类型实现的接口进行类型关联
|
1
2
3
4
5
6
7
8
9
10
11
|
interface I1 { }interface I2 { }interface I3 { }interface I4 { }interface I5 { }interface I6 { }interface I7 { }class C1 : I1, I2, I3, I4, I5, I6, I7{} |
一个类型实现了7个接口,然后我们希望Resolve这七个中任何一个接口,都能获取到C1实例,多关联代码可以简写为:
|
1
2
3
4
5
|
builder.RegisterType<C1>() .As<I1>().As<I2>() .As<I3>().As<I4>() .As<I5>().As<I6>() .As<I7>(); |
然而在有AsImplementInterfaces方法后,就能够非常简单:
|
1
|
builder.RegisterType<C1>().AsImplementedInterfaces(); |
在程序集注册这种方式中,AsImplementInterfaces更能显示出威力,程序集注册这种方式中,都是批量注册类型的,批量注册的这些类型,它们可能都实现了不同的接口,这样我们没办法为它们一一关联接口,但是通过AsImplementInterfaces方法,可以让所有注册类型自动与实现的接口进行关联。当然,也正因为这点,在使用AsImplementInterfaces时需要注意,是否真的希望与所有接口都进行关联。
四 总结(3中关联方式)
a.使用AS关联时一个接口只能与一个类型进行关联
前面将一个类型与多个接口进行关联,让多个接口Resolve结果都是同一个类型实例。这个是不可逆的,也就是一个接口不能与多个类型进行关联,因为这样autofac不知道应该返回哪个类型实例。代码实例:
|
1
2
|
builder.RegisterType<C1>().As<I>(); // class C1 : Ibuilder.RegisterType<C2>().As<I>(); // class C2 : I |
按上面的代码,最后实际与I接口关联的类型是C2,autofac中按注册顺序,后面注册的会覆盖前面注册的。如果想要阻止这种默认行为,可以在As方法调用用继续调用PreserveExistingDefaults方法,这样,如果之前该接口/类型已经进行关联注册,则此次关联无效:
|
1
2
|
builder.RegisterType<C1>().As<I>(); // class C1 : Ibuilder.RegisterType<C2>().As<I>().PreserveExistingDefaults(); // class C2 : I |
上面代码通过Resolve<I>()获取到C1类型实例。注意c1需要实现或继承I
这里说的一个接口不能关联多个类型,是针对这种常用的注册及关联。其实可以通过Named<>、Meta<>这种方式进行多关联
b.一个接口与多个类型关联
builder.RegisterType<Worker>().Named<IPerson>("worker");
builder.RegisterType<Student>().Named<IPerson>("student");
使用Name可以检索服务创建实例:
IPerson p = container.ResolveNamed<IPerson>("worker");
ResolveNamed()只是Resolve()的简单重载,指定名字的服务其实是指定键的服务的简单版本。
c.键
有Name的方式很方便,但是值支持字符串,但有时候我们可能需要通过其他类型作键。
例如,使用枚举作为key:
public enum DeviceState { Worker, Student }
使用key注册服务,通过Keyed<T>()方法:
builder.RegisterType<Student>().Keyed<IPerson>(DeviceState.Student);
IIndex索引
Autofac.Features.Indexed.IIndex<K,V>是Autofac自动实现的一个关联类型。component可以使用IIndex<K,V>作为参数的构造函数从基于键的服务中选择需要的实现。

builder.RegisterType<Student>().Keyed<IPerson>(DeviceState.Student);
using (IContainer container = builder.Build())
{
IIndex<DeviceState, IPerson> IIndex = container.Resolve<IIndex<DeviceState, IPerson>>();
IPerson p = IIndex[DeviceState.Student];
p.Say(); //输出我是一个学生
}

IIndex中第一个泛型参数要跟注册时一致,在例子中是DeviceState枚举。其他两种注册方法没有这样的索引查找功能,这也是为什么设计者推荐Keyed注册的原因之一。
IoC容器Autofac正篇之类型关联(服务暴露)(八)的更多相关文章
- IoC容器Autofac正篇之类型关联(服务暴露)(七)
类型关联 类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例). 一.As关联 我们在进行手动关联时,基本都是使用As进行关联的. class Program { s ...
- IoC容器Autofac正篇之类型注册(四)
Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...
- IoC容器Autofac正篇之类型注册(五)
Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...
- IoC容器Autofac正篇之简单实例
先上一段代码. namespace ConsoleApplication3 { class Program { static void Main(string[] args) { ContainerB ...
- IoC容器Autofac正篇之简单实例(四)
先上一段代码. namespace ConsoleApplication3 { class Program { static void Main(string[] args) { ContainerB ...
- IoC容器Autofac正篇之依赖注入(六)
依赖注入,这个专业词我们可以分为两个部分来理解: 依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A: 注入,医生通过针头将药物 ...
- IoC容器Autofac正篇之依赖注入(七)
依赖注入,这个专业词我们可以分为两个部分来理解: 依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A: 注入,医生通过针头将药物 ...
- IoC容器Autofac正篇之解析获取(五)
解析获取的方式有如下几种: Resolve class Program { static void Main(string[] args) { var builder = new ContainerB ...
- IoC容器Autofac正篇之解析获取(六)
解析获取的方式有如下几种: Resolve class Program { static void Main(string[] args) { var builder = new ContainerB ...
随机推荐
- jdbc_servlet基础增删改分页2(userinfo表的)
1.创建如下文件目录 2.导入MyBatis的jar文件 3.创建实体类 package com.entity; public class Userinfo { private Integer uid ...
- Redis集合相关命令
1.无序集合集合的特性:①确定性②互异性③无序性redis的set是string类型的无序集合set元素最大可以包含(2^32-1)个元素 sadd key value1....valueN 将将元素 ...
- scala集合和高级函数操作
scala常用函数操作 reduceLeft 是将集合的元素从左向右进行所需要的相应操作,图以减法为例展示,表达的算法是 : 1-2-3-4-5 例: (1 to 5).reduceLeft(_ ...
- Apache .htaccess语法之RewriteRule
[说明]定义重写的规则[语法]RewriteRule Pattern rewritePattern [flags] # 开启 rewrite 功能 Options +FollowSymlinks Re ...
- Ubuntu下NFS,TFTP服务搭建
环境:Ubuntu 一. 搭建NFS服务器 (1)安装: sudo apt-get install nfs-kernel-server #安装NFS服务器端 sudo apt-get instal ...
- powder designer 转数据库
1.打开“file new model”
- mysql 批量修改表前缀
直接贴码: SELECT a.*, concat( 'alter table ', a.TABLE_NAME, ' rename ge_', SUBSTR( a.TABLE_NAME FROM INS ...
- 高效PHP程序必知的53个技巧
用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说 ...
- 如何提升 CSS 选择器性能
CSS 选择器性能损耗来自? CSS选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器.而在这之前我们需要了解CSS选择器匹配 ...
- Django中的Form表单
Django中已经定义好了form类,可以很容易的使用Django生成一个表单. 一.利用Django生成一个表单: 1.在应用下创建一个forms文件,用于存放form表单.然后在forms中实例华 ...