autofac 组件的实例范围
实例范围决定如何在请求之间共享服务。
原文地址:http://docs.autofac.org/en/latest/lifetime/instance-scope.html
每个依赖一个实例
使用这个选项,每次请求服务都会返回一个新实例。使用 InstancePerDependency() 指定。这是默认选项。下面的代码,第2行和第3行是等价的。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>();
builder.RegisterType<Worker>().InstancePerDependency();
下面的代码,每次循环都生成一个新的实例,一共生成 100 个实例。
using(var scope = container.BeginLifetimeScope())
{
for(var i = ; i < ; i++)
{
var w = scope.Resolve<Worker>();
w.DoWork();
}
}
单个实例
使用这个选项,在根范围或嵌套范围中请求服务,都返回同一个的实例。使用 SingleInstance() 指定。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().SingleInstance();
下面的代码,w1 和 w2 始终是同一个对象,100 次循环只有一个 Worker 类的实例。
using(var scope1 = container.BeginLifetimeScope())
{
for(var i = ; i < ; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>();
}
}
}
每个生命周期范围一个实例
使用这个选项,在特定的 ILifetimeScope 中请求服务,只返回一个实例。使用 InstancePerLifetimeScope() 指定。下面的代码中,scope1 中的 100 次 w1 是同一个对象,scope2 中的 100 次 w2 是同一个对象,但是 w1 和 w2 不是同一个对象。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerLifetimeScope();
using(var scope1 = container.BeginLifetimeScope())
{
for(var i = ; i < ; i++)
{
var w1 = scope1.Resolve<Worker>();
}
} using(var scope2 = container.BeginLifetimeScope())
{
for(var i = ; i < ; i++)
{
var w2 = scope2.Resolve<Worker>();
}
}
每个匹配的生命周期范围一个实例
类似于上面【每个生命周期范围一个实例】,但可以提供更多控制。使用此选项,允许为 ILifetimeScope 对象提供“标记”。在标记匹配的范围中只有一个实例。使用 InstancePerMatchingLifetimeScope() 方法指定。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerMatchingLifetimeScope("x");
下面的代码中,w1 和 w2 相同,w3 和 w4 相同,但 w1 和 w3 不同。
using(var scope1 = container.BeginLifetimeScope("x"))
{
for(var i = ; i < ; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>();
}
}
}
using(var scope3 = container.BeginLifetimeScope("x"))
{
for(var i = ; i < ; i++)
{
var w3 = scope3.Resolve<Worker>();
using(var scope4 = scope1.BeginLifetimeScope())
{
var w4 = scope4.Resolve<Worker>();
}
}
}
解析时必须提供提供合适的标记,以下代码会抛出异常。
using(var noTagScope = container.BeginLifetimeScope())
{
var fail = noTagScope.Resolve<Worker>();
}
每个请求一个实例
有些应用程序天然具有【请求】语义,例如 ASP.NET MVC 或 WebForm 应用程序。【每个请求一个实例】在【每个匹配的生命周期范围一个实例】基础上,通过提供范围标记,注册函数和常见类型集成实现。本质上是【每个匹配的生命周期范围一个实例】。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerRequest();
ASP.NET Core 使用【每个生命周期范围一个实例】,而不是【每个请求一个实例】。
每个 Owned 一个实例
Owned<T> 隐式关联类型创建嵌套的生命周期范围。使用 instance-per-owned 注册,可将依赖限定在 owned 实例中。
var builder = new ContainerBuilder();
builder.RegisterType<MessageHandler>();
builder.RegisterType<ServiceForHandler>().InstancePerOwned<MessageHandler>();
本例中 ServiceForHandler 服务会限制在 MessageHandler 实例范围内。
using(var scope = container.BeginLifetimeScope())
{
// MessageHandler 和附属的 ServiceForHandler
// 在 scope 下面的一个微型的 lifetime scope 中。
// 解析 Owned<T> 需要程序员负责执行清理工作。
var h1 = scope.Resolve<Owned<MessageHandler>>();
h1.Dispose();
}
线程范围
Autofac 可以强制使A线程的对象不满足B线程的依赖。
var builder = new ContainerBuilder();
builder.RegisterType<MyThreadScopedComponent>()
.InstancePerLifetimeScope();
var container = builder.Build();
然后让每个创建自己的 lifetime scope
void ThreadStart()
{
using (var threadLifetime = container.BeginLifetimeScope())
{
var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
}
}
重要:在多线程场景下,要小心不要将父范围清理掉。否则,派生线程中的子范围将无法解析服务。
每个线程都将有自己的 MyThreadScopedComponent 实例,本质上是生命周期范围内的单例。范围内的实例不会提供到外部,因此很容易保持线程间的组件隔离。
通过添加 ILifetimeScope 参数,可将父范围注入到生成线程的代码中,Autofac 会将当前范围自动注入,接下来可以使用它创建嵌套范围。
public class ThreadCreator
{
private ILifetimeScope _parentScope; public ThreadCreator(ILifetimeScope parentScope)
{
this._parentScope = parentScope;
} public void ThreadStart()
{
using (var threadLifetime = this._parentScope.BeginLifetimeScope())
{
var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
}
}
}
如果想进一步控制,可以使用【每个匹配的生命周期范围一个实例】将线程范围的组件同内部生命周期范围关联起来,这个方式的效果如图:

图中的"Context"是 BeginLifetimeScope 方法创建的生命周期范围。
autofac 组件的实例范围的更多相关文章
- Autofac - 组件
快到年终了, 最近项目比较悠闲, 就想总结下, 项目中所使用到的一些技术, 以及使用方法. 之前有写过Dapper以及Dapper的一个扩展, 这些也是项目中使用过的. 算是一个温故而知新吧. 代码: ...
- Autofac容器对象实例的几种生命周期类型
实例范围决定了如何在同一服务的请求之间共享实例. 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况. 当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作 ...
- SQL Server COM 组件创建实例失败
SQL Server COM 组件创建实例失败 SQL2008数据库总会出现从 IClassFactory 为 CLSID 为 {17BCA6E8-A95D-497E-B2F9-AF6AA4759 ...
- 从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败问题解决方法
从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft ...
- 从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft.Server.manageDTS
从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft ...
- React 深入系列1:React 中的元素、组件、实例和节点
文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...
- Vue组件开发实例(详细注释)
Vue组件开发实例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...
- COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)
从 IClassFactory 为 CLSID 为 {AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2} 的 COM 组件创建实例失败,原因是出现以下错误: c001f011. ...
- vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件) #课程目标 掌握vue实例的相关属性和方法的含义和使用 了解vue的数据响应原理 熟悉创建组件,了解全局 ...
随机推荐
- Win10提示没有权限使用网络资源问题解决
借鉴链接:http://www.cr173.com/html/67361_1.html Win10提示没有权限使用网络资源解决方法 1.打开控制面板; 2.在所有控制面板项中找到凭据管理器; 3.添加 ...
- 【开源】专业K线绘制[K线主副图、趋势图、成交量、滚动、放大缩小、MACD、KDJ等)
这是一个iOS项目雅黑深邃的K线的绘制. 实现功能包括K线主副图.趋势图.成交量.滚动.放大缩小.MACD.KDJ,长按显示辅助线等功能 预览图 最后的最后,这是项目的开源地址:https://git ...
- 图解DevExpress RichEditControl富文本的使用,附源码及官方API
9点半了,刚写到1.2. 该回家了,明天继续写完. 大家还需要什么操作,留言说一下,没有的我明天继续加. 好久没有玩DevExpress了,今天下载了一个玩玩,发现竟然更新到14.2.5了..我去 ...
- Linux LVM逻辑卷配置过程详解
许多Linux使用者安装操作系统时都会遇到这样的困境:如何精确评估和分配各个硬盘分区的容量,如果当初评估不准确,一旦系统分区不够用时可能不得不备份.删除相关数据,甚至被迫重新规划分区并重装操作系统,以 ...
- centos7 安装时候检测不到空余硬盘的解决办法
我是用U盘装的centos,在进行硬盘规划时,看到硬盘的可用空间太少 这是因为我的硬盘以前装的是windows系统,硬盘几乎都已经被windows 操作系统给使用了,剩余空间也只会是windows用剩 ...
- Linux设备管理(五)_写自己的sysfs接口
我们在Linux设备管理(一)_kobject, kset,ktype分析一文中介绍了kobject的相关知识,在Linux设备管理(二)_从cdev_add说起和Linux设备管理(三)_总线设备的 ...
- Linux实战教学笔记01:计算机硬件组成与基本原理
标签(空格分隔): Linux实战教学笔记 第1章 如何学习Linux 要想学好任何一门学问,不仅要眼睛看,耳朵听,还要动手记,勤思考,多交流甚至尝试着去教会别人. 第2章 服务器 2.1 运维的基本 ...
- JAVA通信系列三:Netty入门总结
一.Netty学习资料 书籍<Netty In Action中文版> 对于Netty的十一个疑问http://news.cnblogs.com/n/205413/ 深入浅出Nettyhtt ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- epoll LT/ET 深度剖析
EPOLL事件的两种模型: Level Triggered (LT) 水平触发 .socket接收缓冲区不为空 有数据可读 读事件一直触发 .socket发送缓冲区不满 可以继续写入数据 写事件一直触 ...