Autofac之类型关联
前面的学习一直使用的是直接注册类型并不是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之类型关联的更多相关文章
- IoC容器Autofac正篇之类型关联(服务暴露)(七)
类型关联 类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例). 一.As关联 我们在进行手动关联时,基本都是使用As进行关联的. class Program { s ...
- IoC容器Autofac正篇之类型关联(服务暴露)(八)
类型关联 类型关联就是将类挂载到接口(一个或多个)上去,以方便外部以统一的方式进行调用(看下例). 一.As关联 我们在进行手动关联时,基本都是使用As进行关联的. 1 2 3 4 5 6 7 8 ...
- WebStorm文件类型关联设置
无意中创造了一个没有扩展名的文件,我选择了错误的文件类型关联.是js类型的,我却选成了文本,Ws每次编辑类型就成了txt文本,这个问题让我很苦恼,以下是我的解决方案. 错选的弹出框如下: 解决方案如下 ...
- Vim使用技巧:特定文件类型关联缩进
Vim如何打开特定文件类型关联自动缩进呢?答案:将filetype indent on写入你的.vimrc文件中
- 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议
[源码下载] 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议 作者:webabcd 介绍背水一战 Windows 10 之 关联启动 关联指定的文件类型 ...
- Windows的文件类型关联
在用脚本语言开发时尤其是在windows环境下发现想自动在命令行环境下运行脚本必须要带着相应的解释器的路径才行,不然就会提示无法找到对应的命令,于是乎在<学习Ruby>这本书中对于文件类型 ...
- Autofac之类型注册
本次主要学习一下Autofac中实现类型注册的几种方式,这里并不打算一开始就从基于接口开发的服务关联切入,而是先从一个简单的类型注册来学起,虽然实际开发中可能不会这么做,但是个人感觉从这里学起理解能能 ...
- Swift - 39 - 枚举类型关联默认值
//: Playground - noun: a place where people can play import UIKit enum Month: Int { // 这么定义, 后面的Feb, ...
- 【Loadrunner】初学Loadrunner——参数化设置(Table类型关联数据库)
参数化输入是Loadrrunner里面一个强大的功能,属于Loadrunner的高级使用技巧. 我们在登录系统的时候,需要输入一组定义的用户名和密码,比如有5个虚拟用户同时登陆系统,则这五个用户都用这 ...
随机推荐
- SQL中笛卡尔积-cross join的用法
在数学中,笛卡尔乘积是指两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 假设集合A={a ...
- 结构体重载运算符&srand&rand
先上代码,再按代码讲解 #include<stdio.h>#include<string.h>#include<stdlib.h>#include<time. ...
- C#+EntityFramework编程方式详细之Database First
Database First “Database First”模式即“数据库优先”,其实Database First 与Model First 很类似,只不过一个是有数据可一个是创建数据库,具体的操作 ...
- HDU 2196 Compute --树形dp
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Java的家庭记账本程序(L)
日期:2019.3.13 博客期:044 星期三 整理了两天,我终于也是把微信小程序平台的记账本软件完全开发出来了,并将我的微信账号与GitHub账号完成了绑定,那么我就先展示一部分作品,还有一部分代 ...
- jsp 异步处理
一. 概述 异步处理功能可以节约容器线程.你应该将此功能 使用在长时间运行的操作上.此功能的作用是释放正在 等待完成的线程,使该线程能够被另一请求所使用. 二. 编写异步Servlet和过滤器 We ...
- jetbrains的JetBrains PyCharm 2018.3.1破解激活到2100年(最新亲测可用)
破解补丁激活 之前看了好多的其它的方法感觉都不是很靠谱还是这个本人亲试可以长期有效不仅能激活pycharm.jetbrains的JetBrains PyCharm 2018.3.1破解激活到2100年 ...
- django第三天
从后台传入一层的字典数据 后台代码 前台代码一 浏览器结果 前台代码二 前台代码三 前台代码四 注意 默认遍历为KEY .values .keys .items 都不加括号
- main函数中System.exit()的作用
main()主函数再熟悉不过,了解java的人也都知道System.exit()方法是停止虚拟机运行.那这里为什么还要单独写一篇博客,都是源于朋友发的一张最近刚买的T恤照片,就是上面这张图.这是一个经 ...
- [转] vue从入门到进阶:组件Component详解(六)
https://www.cnblogs.com/moqiutao/p/8328931.html