实例范围决定如何在请求之间共享服务。

原文地址:http://docs.autofac.org/en/latest/lifetime/instance-scope.html

每个依赖一个实例

使用这个选项,每次请求服务都会返回一个新实例。使用 InstancePerDependency() 指定。这是默认选项。下面的代码,第2行和第3行是等价的。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<Worker>();
  3. builder.RegisterType<Worker>().InstancePerDependency();

下面的代码,每次循环都生成一个新的实例,一共生成 100 个实例。

  1. using(var scope = container.BeginLifetimeScope())
  2. {
  3. for(var i = ; i < ; i++)
  4. {
  5. var w = scope.Resolve<Worker>();
  6. w.DoWork();
  7. }
  8. }

单个实例

使用这个选项,在根范围或嵌套范围中请求服务,都返回同一个的实例。使用 SingleInstance() 指定。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<Worker>().SingleInstance();

下面的代码,w1 和 w2 始终是同一个对象,100 次循环只有一个 Worker 类的实例。

  1. using(var scope1 = container.BeginLifetimeScope())
  2. {
  3. for(var i = ; i < ; i++)
  4. {
  5. var w1 = scope1.Resolve<Worker>();
  6. using(var scope2 = scope1.BeginLifetimeScope())
  7. {
  8. var w2 = scope2.Resolve<Worker>();
  9. }
  10. }
  11. }

每个生命周期范围一个实例

使用这个选项,在特定的 ILifetimeScope 中请求服务,只返回一个实例。使用 InstancePerLifetimeScope() 指定。下面的代码中,scope1 中的 100 次 w1 是同一个对象,scope2 中的 100 次 w2 是同一个对象,但是 w1 和 w2 不是同一个对象。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<Worker>().InstancePerLifetimeScope();
  3. using(var scope1 = container.BeginLifetimeScope())
  4. {
  5. for(var i = ; i < ; i++)
  6. {
  7. var w1 = scope1.Resolve<Worker>();
  8. }
  9. }
  10.  
  11. using(var scope2 = container.BeginLifetimeScope())
  12. {
  13. for(var i = ; i < ; i++)
  14. {
  15. var w2 = scope2.Resolve<Worker>();
  16. }
  17. }

每个匹配的生命周期范围一个实例

类似于上面【每个生命周期范围一个实例】,但可以提供更多控制。使用此选项,允许为 ILifetimeScope 对象提供“标记”。在标记匹配的范围中只有一个实例。使用 InstancePerMatchingLifetimeScope() 方法指定。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<Worker>().InstancePerMatchingLifetimeScope("x");

下面的代码中,w1 和 w2 相同,w3 和 w4 相同,但 w1 和 w3 不同。

  1. using(var scope1 = container.BeginLifetimeScope("x"))
  2. {
  3. for(var i = ; i < ; i++)
  4. {
  5. var w1 = scope1.Resolve<Worker>();
  6. using(var scope2 = scope1.BeginLifetimeScope())
  7. {
  8. var w2 = scope2.Resolve<Worker>();
  9. }
  10. }
  11. }
  12.  
  13. using(var scope3 = container.BeginLifetimeScope("x"))
  14. {
  15. for(var i = ; i < ; i++)
  16. {
  17. var w3 = scope3.Resolve<Worker>();
  18. using(var scope4 = scope1.BeginLifetimeScope())
  19. {
  20. var w4 = scope4.Resolve<Worker>();
  21. }
  22. }
  23. }

解析时必须提供提供合适的标记,以下代码会抛出异常。

  1. using(var noTagScope = container.BeginLifetimeScope())
  2. {
  3. var fail = noTagScope.Resolve<Worker>();
  4. }

每个请求一个实例

有些应用程序天然具有【请求】语义,例如 ASP.NET MVC 或 WebForm 应用程序。【每个请求一个实例】在【每个匹配的生命周期范围一个实例】基础上,通过提供范围标记,注册函数和常见类型集成实现。本质上是【每个匹配的生命周期范围一个实例】。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<Worker>().InstancePerRequest();

ASP.NET Core 使用【每个生命周期范围一个实例】,而不是【每个请求一个实例】。

每个 Owned 一个实例

Owned<T> 隐式关联类型创建嵌套的生命周期范围。使用 instance-per-owned 注册,可将依赖限定在 owned 实例中。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<MessageHandler>();
  3. builder.RegisterType<ServiceForHandler>().InstancePerOwned<MessageHandler>();

本例中 ServiceForHandler 服务会限制在 MessageHandler 实例范围内。

  1. using(var scope = container.BeginLifetimeScope())
  2. {
  3. // MessageHandler 和附属的 ServiceForHandler
    // 在 scope 下面的一个微型的 lifetime scope 中。
    // 解析 Owned<T> 需要程序员负责执行清理工作。
  4. var h1 = scope.Resolve<Owned<MessageHandler>>();
  5. h1.Dispose();
  6. }

线程范围

Autofac 可以强制使A线程的对象不满足B线程的依赖。

  1. var builder = new ContainerBuilder();
  2. builder.RegisterType<MyThreadScopedComponent>()
  3. .InstancePerLifetimeScope();
  4. var container = builder.Build();

然后让每个创建自己的 lifetime scope

  1. void ThreadStart()
  2. {
  3. using (var threadLifetime = container.BeginLifetimeScope())
  4. {
  5. var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
  6. }
  7. }

重要:在多线程场景下,要小心不要将父范围清理掉。否则,派生线程中的子范围将无法解析服务。

每个线程都将有自己的 MyThreadScopedComponent 实例,本质上是生命周期范围内的单例。范围内的实例不会提供到外部,因此很容易保持线程间的组件隔离。

通过添加 ILifetimeScope 参数,可将父范围注入到生成线程的代码中,Autofac 会将当前范围自动注入,接下来可以使用它创建嵌套范围。

  1. public class ThreadCreator
  2. {
  3. private ILifetimeScope _parentScope;
  4.  
  5. public ThreadCreator(ILifetimeScope parentScope)
  6. {
  7. this._parentScope = parentScope;
  8. }
  9.  
  10. public void ThreadStart()
  11. {
  12. using (var threadLifetime = this._parentScope.BeginLifetimeScope())
  13. {
  14. var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
  15. }
  16. }
  17. }

如果想进一步控制,可以使用【每个匹配的生命周期范围一个实例】将线程范围的组件同内部生命周期范围关联起来,这个方式的效果如图:

图中的"Context"是 BeginLifetimeScope 方法创建的生命周期范围。

autofac 组件的实例范围的更多相关文章

  1. Autofac - 组件

    快到年终了, 最近项目比较悠闲, 就想总结下, 项目中所使用到的一些技术, 以及使用方法. 之前有写过Dapper以及Dapper的一个扩展, 这些也是项目中使用过的. 算是一个温故而知新吧. 代码: ...

  2. Autofac容器对象实例的几种生命周期类型

    实例范围决定了如何在同一服务的请求之间共享实例. 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况. 当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作 ...

  3. SQL Server COM 组件创建实例失败

    SQL Server COM 组件创建实例失败   SQL2008数据库总会出现从 IClassFactory 为 CLSID 为 {17BCA6E8-A95D-497E-B2F9-AF6AA4759 ...

  4. 从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败问题解决方法

    从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft ...

  5. 从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft.Server.manageDTS

    从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft ...

  6. React 深入系列1:React 中的元素、组件、实例和节点

    文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...

  7. Vue组件开发实例(详细注释)

    Vue组件开发实例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  8. COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)

    从 IClassFactory 为 CLSID 为 {AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2} 的 COM 组件创建实例失败,原因是出现以下错误: c001f011. ...

  9. vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)

    第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件) #课程目标 掌握vue实例的相关属性和方法的含义和使用 了解vue的数据响应原理 熟悉创建组件,了解全局 ...

随机推荐

  1. 【MySql】查询数据库中所有表及列的信息

    SELECT TABLE_NAME, -- 表名 COLUMN_NAME, -- 字段名 DATA_TYPE, -- 字段类型 COLUMN_COMMENT -- 字段注释 FROM INFORMAT ...

  2. Windows 7 上安装Visual Studio 2015 失败解决方案

    安装之前先要看看自己的系统支不支持,具体的可以看:https://www.visualstudio.com/en-us/visual-studio-2015-system-requirements-v ...

  3. 【Win10】UAP/UWP/通用 开发之 x:Bind

    [Some information relates to pre-released product which may be substantially modified before it's co ...

  4. 【腾讯Bugly干货分享】程序员们也该知道的事——“期权和股票”

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/pfj9NLLuKYAfJJF84R9WAw 作者:B ...

  5. H5嵌入原生开发小结----兼容安卓与ios的填坑之路

    一开始听说开发H5,以为就是做适配现代浏览器的移动网页,心想不用管IE了,欧也.到今天,发现当初too young too simple,兼容IE和兼容安卓与IOS,后者让你更抓狂.接下来数一下踩过的 ...

  6. 实现了一个百度首页的彩蛋——CSS3 Animation简介

    在百度搜索中有这样一个彩蛋:搜索“旋转”,“跳跃”,“反转”等词语,会出现相应的动画效果(搜索“反转”后的效果).查看源码可以发现,这些效果正是通过CSS3的animation属性实现的. 实现这个彩 ...

  7. 提高代码质量系列之二:重构小技巧——if篇

    前言: if,相信是童鞋们使用的最频繁的关键字了,而且很多时候,我们使用的if都是在无意识的状态下随手而为.键入if,两下回车(我使用了resharper,可以自动编排if的格式),再信手写下我们需要 ...

  8. ABP框架 - 集成OWIN

    文档目录 如果你在应用中同时使用Asp.net Mvc和Asp.net Web API,你需要在你的项目里添加Abp.Owin的nuget包(通常是Web项目)然后在你的OWIN的Startup文件里 ...

  9. Memcached和Redis比较

    一.存储 Memcached基本只支持简单的key-value存储方式.Redis除key-value之外,还支持list,set,sorted set,hash等数据结构:Redis支持数据的备份, ...

  10. 在linux平台实现atosl

    ➠更多技术干货请戳:听云博客 序言 怎么在linux 平台下实现一个类似于mac 平台下的 atos 工具( iOS 符号化解析)? 分析问题 在github上找到了几年前的开源实现,[https:/ ...