类型关联

类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例)。

一.As关联

我们在进行手动关联时,基本都是使用As进行关联的.

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而不抛出异常,应该怎么办呢?

// 这两句代码效果相同
builder.RegisterType<Class1>().As<IInterface>().As<Class1>();
builder.RegisterType<Class1>().As<IInterface>().AsSelf();

三 批量关联AsImplementedInerfaces

AsImplementedInterfaces也就是直接与类型实现的接口进行类型关联

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实例,多关联代码可以简写为:

builder.RegisterType<C1>()
.As<I1>().As<I2>()
.As<I3>().As<I4>()
.As<I5>().As<I6>()
.As<I7>();

  然而在有AsImplementInterfaces方法后,就能够非常简单:

builder.RegisterType<C1>().AsImplementedInterfaces();

  在程序集注册这种方式中,AsImplementInterfaces更能显示出威力,程序集注册这种方式中,都是批量注册类型的,批量注册的这些类型,它们可能都实现了不同的接口,这样我们没办法为它们一一关联接口,但是通过AsImplementInterfaces方法,可以让所有注册类型自动与实现的接口进行关联。当然,也正因为这点,在使用AsImplementInterfaces时需要注意,是否真的希望与所有接口都进行关联。

四 总结(3中关联方式)

a.使用AS关联时一个接口只能与一个类型进行关联

前面将一个类型与多个接口进行关联,让多个接口Resolve结果都是同一个类型实例。这个是不可逆的,也就是一个接口不能与多个类型进行关联,因为这样autofac不知道应该返回哪个类型实例。代码实例:

builder.RegisterType<C1>().As<I>(); // class C1 : I
builder.RegisterType<C2>().As<I>(); // class C2 : I

  按上面的代码,最后实际与I接口关联的类型是C2,autofac中按注册顺序,后面注册的会覆盖前面注册的。如果想要阻止这种默认行为,可以在As方法调用用继续调用PreserveExistingDefaults方法,这样,如果之前该接口/类型已经进行关联注册,则此次关联无效:

builder.RegisterType<C1>().As<I>(); // class C1 : I
builder.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正篇之类型关联(服务暴露)(七)的更多相关文章

  1. IoC容器Autofac正篇之类型关联(服务暴露)(八)

    类型关联  类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例). 一.As关联 我们在进行手动关联时,基本都是使用As进行关联的. 1 2 3 4 5 6 7 8 ...

  2. IoC容器Autofac正篇之类型注册(四)

    Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...

  3. IoC容器Autofac正篇之类型注册(五)

    Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...

  4. IoC容器Autofac正篇之简单实例

    先上一段代码. namespace ConsoleApplication3 { class Program { static void Main(string[] args) { ContainerB ...

  5. IoC容器Autofac正篇之简单实例(四)

    先上一段代码. namespace ConsoleApplication3 { class Program { static void Main(string[] args) { ContainerB ...

  6. IoC容器Autofac正篇之依赖注入(六)

    依赖注入,这个专业词我们可以分为两个部分来理解: 依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A: 注入,医生通过针头将药物 ...

  7. IoC容器Autofac正篇之依赖注入(七)

    依赖注入,这个专业词我们可以分为两个部分来理解: 依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A: 注入,医生通过针头将药物 ...

  8. IoC容器Autofac正篇之解析获取(五)

    解析获取的方式有如下几种: Resolve class Program { static void Main(string[] args) { var builder = new ContainerB ...

  9. IoC容器Autofac正篇之解析获取(六)

    解析获取的方式有如下几种: Resolve class Program { static void Main(string[] args) { var builder = new ContainerB ...

随机推荐

  1. Word文档分割总结

    Word文档分割总结 方法: 1. word创建子文件实现文件分割 2. VBA实现 3. 网上分割合并的插件软件 一. word创建子文件实现文件分割 打开需要分割的文件 >> 视图 & ...

  2. 搭建LAMP架构

    1. 为什么下载源码包需要到官网上去下载?简单说就是为了安全,如果是非官方下载的源码包,有可能被别有用心的人动过手脚. 2. 64位机器是否可以安装32位rpm包?64位机器是否可以安装32位的mys ...

  3. Oracle语句块PL/SQL循环判断

    - --pl/sql Procedural Language /sql --被数据库编译保存,由用户调用 --程序块 /* 语法 Declare – 声明变量 --声明变量 Age int; //没有 ...

  4. OpenGL ES 2.0 曲面物体的构建

    球体构建的基本原理构建曲面物体最重要的就是找到将曲面恰当拆分成三角形的策略. 最基本的策略是首先按照一定的规则将物体按行和列两个方向进行拆分,这时就可以得到很多的小四边形.然后再将每个小四边形拆分成两 ...

  5. CentOS FTP服务器权限控制

    在默认配置下,本地用户登入FTP后可以使用cd命令切换到其他目录,这样会对系统带来安全隐患.可以通过以下三条配置文件来控制用户切换目录. chroot_list_enable=YES/NO(NO) 设 ...

  6. Java如何获取当前的jar包路径以及如何读取jar包中的资源

    写作业的时候要输出一个record.dat文件到jar包的同级目录,但是不知道怎么定位jar包的路径.百度到的方法不很靠谱,所以在这里记录一下. 一:使用类路径 String path = this. ...

  7. jquery国内cdn

    推荐几个国内的jquery CDN服务地址吧: 新浪CDN,感觉很快,用的人很多,推荐使用! http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.m ...

  8. a标签加绝对定位在图片上面,a的链接和块状属性block失效,而且是所有IE版本都失效的

    谷歌和火狐浏览器下测试是正常的,IE下鼠标移过logo是没有超链接的提示的 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...

  9. MySQL中的两个时间函数,用来做两个时间之间的对比

    TIMESTAMPDIFF,(如果当期时间和之前时间的分钟数相比较.大于1天,即等于1:小于1天,则等于0) select TIMESTAMPDIFF(DAY,'2016-11-16 10:13:42 ...

  10. TypeScript开发Vue

    用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象 目录 背景 解决方案 关于Vue中的计算属性类型 TypeScript的强制类型声明语法 强制类型声明的局限 ...