IOC,控制反转(Inversion of Control)把创建对象的权利交给框架,是框架的重要特征,并非面向对象编程的专用术语。它包括依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。
项目中使用借口驱动,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,会产生耦合关系。通过IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中。
- 控制反转(IoC/Inverse Of Control): 调用者不再创建被调用者的实例,由autofac框架实现(容器创建)所以称为控制反转。
- 依赖注入(DI/Dependence injection) : 容器创建好实例后再注入调用者称为依赖注入。
本来想自己写的,看到这篇感觉蛮详细的了,具体的看这篇教程:https://www.cnblogs.com/liupeng/p/4806184.html
笔记
注册类型及其实例
1.使用Per Dependency作用域,服务对于每次请求都会返回单独的实例。
builder.RegisterType<X>();
// or
builder.RegisterType<X>().InstancePerDependency();
|
2.使用Single Instance作用域,所有对父容器或者嵌套容器的请求都会返回同一个实例。
builder.RegisterType<X>().SingleInstance();
泛型
给定一个开放的泛型,Autofac会提供一个具体的实现。
开放的泛型类型使用泛型服务注册,给定一个服务类型和一个实现类型
|
public
interface
IRepository<T> { }
public
class
NHibernateRepository<T> : IRepository<T> { }
|
使用RegisterGeneric配置容器
builder.RegisterGeneric(
typeof
(NHibernateRepository<>)).As(
typeof
(IRepository<>));
当检索一个具体的服务时,会正确的得到一个具体的实现类型:
// Returns NHibernateRepository<User>
var
userRepo = container.Resolve<IRepository<User>>();
|
关系类型
Autofac提供拆箱即用的关系类型。
Autofac会对下面列出的关系类型特别解释。下面列出的每一种关系类型,Autofac都会在需要的时候提供一种默认实现。
比如说,当Autofac会 IEnumerable 类型的构造函数参数进行注入时,它不会寻找提供 IEnumerable 的component,而是容器会找出所有的ITasks实现然后全部注入。
(你可以显示注册这些类型的实现来覆盖默认行为)
Relationship | Type | Meaning |
A needs B | B | Dependency |
A needs B at some point in the future | Lazy<B> | Delayed instantiation |
A needs B until some point in the future | Owned<B> | Controlled lifetime |
A needs to create instances of B | Func<B> | Dynamic instantiation |
A provides parameters of types X and Y to B | Func<X,Y,B> | Parameterisation |
A needs all the kinds of B | IEnumerable<B> | Enumeration |
A needs to know X about B | Meta<T> and Meta<B,X> | Metadata interrogation |
A needs to choose B based on X | IIndex<X,B> | Lookup |
Resolve的参数
当注册或者检索component的时候可以使用参数
Resolve接受可变长度的参数列表
1
|
var
fred = Resolve<Person>(
new
NamedParameter(
"name"
,
"Fred"
));
|
可用的参数类型
Autofac提供几种不同的参数对应策略
- NamedParameter -像上面那样对应的参数名字
- TypedParameter -对应到参数的类型(必须是具体的类型)
- ResolvedParameter 灵活的参数匹配
NamedParameter 和TypedParameter 只能提供常量参数
从表达式中使用参数
如果Person是使用表达式注册的,可以使用第二个可用的委托参数(IEnumerable类型)来获得参数。
1
|
builder.Register((c, p) =>
new
Person(p.Named<
string
>(
"name"
)));
|
属性注入
属性注入使用可写属性而不是构造函数参数实现注入。
介绍
如果component是一个委托,使用一个对象初始化:
1
|
builder.Register(c =>
new
A { B = c.Resolve<B>() });
|
为了提供循环依赖(就是当A使用B的时候B已经初始化),需要使用OnActivated事件接口:
1
|
builder.Register(c =>
new
A()).OnActivated(e => e.Instance.B = e.Context.Resolve<B>());
|
通过发射,使用PropertiesAutowired()修饰符注入属性。
1
|
builder.RegisterType<A>().PropertiesAutowired();
|
如果你预先知道属性的名字和值,你可以使用
1
|
builder.WithProperty(
"propertyName"
, propertyValue)。
|
激活事件
在component生命周期的不同阶段使用事件。
Autofac暴露三个事件接口供实例的不同阶段调用
- OnActivating
- OnActivated
- OnRelease
这些事件会在注册的时候被订阅,或者被附加到IComponentRegistration 的时候
1
|
builder.RegisterType<Listener>().OnActivated(e => e.Instance.StartListening());
|
OnActivating
component被创建之前调用,在这里你可以
- 将实例转向另外一个或者使用代理封装它
- 进行属性注入
- 执行其他初始化工作
OnActivated
在component被完全创建的时候调用一次。在这个时候你可以执行程序级别的一些工作(这些工作依赖于对象被完全创建)-这种情况很罕见。
OnRelease
替代component的标准清理方法。实现了IDisposable 接口的标准清理方法(没有标记为ExternallyOwned) 通过调用Dispose 方法。没有实现IDisposable或者被标记为ExternallyOwned的清理方法是一个空函数-不执行任何操作。OnRelease 就是用来覆盖默认的清理行为的。