前面的学习一直使用的是直接注册类型并不是Autofac已经依赖注入的主要使用方式,最佳的依赖注入与Autofac的使用方式,都是要结合面向接口(抽象)编程的概念的。推崇的是依赖于抽象而不是具体

public interface IPerson
{
void Say();
} public class Worker : IPerson
{
public void Say()
{
Console.WriteLine("工人!");
}
} public class Student : IPerson
{
public void Say()
{
Console.WriteLine("学生!");
}
} public class AutoFacManager
{
IPerson person; public AutoFacManager(IPerson MyPerson)
{
person = MyPerson;
} public void Say()
{
person.Say();
}
}

使用AS进行关联

//IPerson类型的服务和Worker的组件连接起来,这个服务可以创建Worker类的实例
builder.RegisterType<Worker>().As<IPerson>();
using (var container = builder.Build())
{
var obj = container.Resolve<IPerson>();
obj.Say();
}

多关联

public interface IPerson
{
void Say();
}
public interface IDuty
{
void Write();
} public class Worker : IPerson, IDuty
{
public void Say()
{
Console.WriteLine("工人!");
} public void Write()
{
Console.WriteLine("我的工作内容是搬砖!");
}
}

一个类可能实现多个接口,如果我们希望Resolve多个接口时获取到的都是那个类型,应该怎么做呢?最容易想到的方式就是直接再注册As一遍就好了。Autofac提供了类似IEnumerable和IQueryable链式编程的方式,如果希望多个接口或类型都与同一个类型进行关联,我们可以直接在表达式后面继续As

builder.RegisterType<Worker>()
.As<IPerson>()
.As<IDuty>();
using (var container = builder.Build())
{
var obj1 = container.Resolve<IPerson>();
var obj2 = container.Resolve<IDuty>();
obj1.Say();
obj2.Write();

自关联AsSelf

不使用As时,RegisterType注册的是什么类型,Resolve就使用什么类型进行获取,但是在使用As后,就只能使用As的类型进行Resolve;但是如果还想在Resolve<Worker>时能够获取到Worker而不抛出异常,应该怎么办呢?在不知道AsSelf方法的情况下,可以在注册时直接As<Worker>,这样就可以了。另一种方式就是AsSelf

builder.RegisterType<Worker>().As<IPerson>();//这么写获取实例必须使用As类型进行Resolve
builder.RegisterType<Worker>().As<IPerson>().AsSelf();//这么写可以使用原类型进行Resolve
using (var container = builder.Build())
{
var obj1 = container.Resolve<Worker>();//builder.RegisterType<Worker>().As<IPerson>().As<Worker>();或者builder.RegisterType<Worker>().As<IPerson>().AsSelf();都可以
var obj2 = container.Resolve<IPerson>();//必须builder.RegisterType<Worker>().As<IPerson>();
obj1.Say();
obj2.Say();
}

批量关联AsImplementedInerfaces

之前说到可以通过多个As为一个类型关联多个接口,但是如果实现接口过多代码还是不够简洁,通过AsImplementInterfaces方法,可以让所有注册类型自动与实现的接口进行关联。当然,也正因为这点,在使用AsImplementInterfaces时需要注意,是否真的希望与所有接口都进行关联

builder.RegisterType<Worker>().AsImplementedInterfaces();
using (var container = builder.Build())
{
var obj1 = container.Resolve<IPerson>();
var obj2 = container.Resolve<IDuty>();
obj1.Say();
obj2.Write();
}

类型关联注意点

一个接口/类型只能与一个类型进行关联,前面我们看到了,可以将一个类型与多个接口进行关联,让多个接口Resolve结果都是同一个类型实例。需要注意的是,这个是不可逆的,也就是一个接口不能与多个类型进行关联,因为这样autofac不知道应该返回哪个类型实例

builder.RegisterType<Worker>().As<IPerson>();
builder.RegisterType<Student>().As<IPerson>();
using (var container = builder.Build())
{
var obj = container.Resolve<IPerson>();
obj.Say();
}

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

关联类型与注册类型需要时继承/实现关系或为其本身

builder.RegisterType<X>().As<Y>();

当这样进行注册关联时,需要X继承或实现Y,再或者Y就是X类型,否则将在builder调用Build方法时抛出异常。

1、类型

类型是描述服务的基本方法

builder.RegisterType<Worker>().As<IPerson>();  //IPerson类型的服务和Worker的组件连接起来,这个服务可以创建Worker类的实例

2、名字

服务可以进一步按名字识别。使用这种方式时,用 Named()注册方法代替As()以指定名字

builder.RegisterType<Worker>().Named<IPerson>("worker");
builder.RegisterType<Student>().Named<IPerson>("student");
using (var container = builder.Build())
{
var obj1 = container.ResolveNamed<IPerson>("worker");
obj1.Say();
var obj2 = container.ResolveNamed<IPerson>("student");
obj2.Say();
}

3、键

有Name的方式很方便,但是值支持字符串,但有时候我们可能需要通过其他类型作键。

例如,使用枚举作为key:

public enum State { Worker, Student }
builder.RegisterType<Worker>().Keyed<IPerson>(State.Worker);
builder.RegisterType<Student>().Keyed<IPerson>(State.Student);
using (var container = builder.Build())
{
var obj1 = container.ResolveKeyed<IPerson>(State.Worker);
obj1.Say();
var obj2 = container.ResolveKeyed<IPerson>(State.Student);
obj2.Say();
}

ResolveKeyd()会导致容器被当做 Service Locator使用,这是不被推荐的。应该使用IIndex type替代。

IIndex索引,需要using Autofac.Features.Indexed

Autofac.Features.Indexed.IIndex<K,V>是Autofac自动实现的一个关联类型。component可以使用IIndex<K,V>作为参数的构造函数从基于键的服务中选择需要的实现

builder.RegisterType<Student>().Keyed<IPerson>(State.Student);
using (IContainer container = builder.Build())
{
IIndex<State, IPerson> IIndex = container.Resolve<IIndex<State, IPerson>>();
IPerson p = IIndex[State.Student];
p.Say();
}

IIndex中第一个泛型参数要跟注册时一致,在例子中是State枚举。其他两种注册方法没有这样的索引查找功能,这也是为什么设计者推荐Keyed注册的原因之一

Autofac之类型关联的更多相关文章

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

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

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

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

  3. WebStorm文件类型关联设置

    无意中创造了一个没有扩展名的文件,我选择了错误的文件类型关联.是js类型的,我却选成了文本,Ws每次编辑类型就成了txt文本,这个问题让我很苦恼,以下是我的解决方案. 错选的弹出框如下: 解决方案如下 ...

  4. Vim使用技巧:特定文件类型关联缩进

    Vim如何打开特定文件类型关联自动缩进呢?答案:将filetype indent on写入你的.vimrc文件中

  5. 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议

    [源码下载] 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议 作者:webabcd 介绍背水一战 Windows 10 之 关联启动 关联指定的文件类型 ...

  6. Windows的文件类型关联

    在用脚本语言开发时尤其是在windows环境下发现想自动在命令行环境下运行脚本必须要带着相应的解释器的路径才行,不然就会提示无法找到对应的命令,于是乎在<学习Ruby>这本书中对于文件类型 ...

  7. Autofac之类型注册

    本次主要学习一下Autofac中实现类型注册的几种方式,这里并不打算一开始就从基于接口开发的服务关联切入,而是先从一个简单的类型注册来学起,虽然实际开发中可能不会这么做,但是个人感觉从这里学起理解能能 ...

  8. Swift - 39 - 枚举类型关联默认值

    //: Playground - noun: a place where people can play import UIKit enum Month: Int { // 这么定义, 后面的Feb, ...

  9. 【Loadrunner】初学Loadrunner——参数化设置(Table类型关联数据库)

    参数化输入是Loadrrunner里面一个强大的功能,属于Loadrunner的高级使用技巧. 我们在登录系统的时候,需要输入一组定义的用户名和密码,比如有5个虚拟用户同时登陆系统,则这五个用户都用这 ...

随机推荐

  1. day02 解释器安装及初识变量

    今日内容: 1.解释器的安装 2.添加到环境变量 3.pip初识 4.变量初识 5.PyCharm安装及激活 今日重点: 1.将python及pip添加到环境变量 在将python解释器安装到计算机后 ...

  2. Beta冲刺(7/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(7/7) 后敬甲(组长) 过去两天完成了哪些任务 ppt制作 视频拍摄 接下来的计划 准备答辩 还剩下哪些 ...

  3. @Autowired mapper 层次 bean 带红线

    在利用@Autowired 注解创建bean 时候 有时间会带有下滑红色横线 给人一种报错的感觉 下面是去除红线的办法 将颜色红色error 等级降低为黄色warn  即可

  4. 连接慢的主要原因是DNS解析导致

    连接慢的主要原因是DNS解析导致解决方法: 1.在ssh服务端上更改/etc/ssh/sshd_config文件中的配置为如下内容:UseDNS no# GSSAPI optionsGSSAPIAut ...

  5. python——常见排序算法解析

    算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序, ...

  6. webpack proxyTable 跨域

    dev-server能在开发环境中生成一个本地服务器来实现代理 在vue-cli下 找的 dev下的 proxyTable: { '/':{ //前缀 target: 'http://www.exam ...

  7. loj6077

    题解: 网上的做法好像都是容斥 那就先说一下容斥 首先问题等价于求下面这个式子的方案数 $$\sum_{i=1}^{n} ai (0<ai<i) =k$$ 直接$dp$复杂度是$nk$的, ...

  8. Redis数据结构之quicklist

    本文及后续文章,Redis版本均是v3.2.8 我们在使用Redis对外暴露的list数据结构时,给我们带来极大的便利性.其底层实现所依赖的内部数据结构就是quicklist. 我们先来回忆下list ...

  9. Codeforces 461D. Appleman and Complicated Task 构造,计数

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF461D.html 题解 首先我们可以发现如果确定了第一行,那么方案就唯一了. 然后,我们来看看一个点的值确定 ...

  10. LCA最近公共祖先

    不会 准备研究一波!!! #include<bits/stdc++.h> ; using namespace std; vector<int> g[maxn]; ][maxn] ...