实例范围决定了如何在同一服务的请求之间共享实例。 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况。

当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作用域)或某种上下文中的单个实例,例如 线程或HTTP请求(每个生命周期范围)。

这适用于从显式Resolve()调用返回的实例以及容器内部创建的实例,以满足另一个组件的依赖关系。

选择正确的生命周期范围将有助于避免组件寿命过长或不够长的俘获依赖和其他陷阱。 开发人员需要为每个应用程序组件做出正确的选择。

1.Instance Per Dependency

每次都会返回一个新的实例,并且这是默认的生命周期。

  1. var builder = new ContainerBuilder();
  2. // This...
  3. builder.RegisterType<Worker>();
  4. // 此句代码的效果同上
  5. builder.RegisterType<Worker>().InstancePerDependency();

当您解析每个依赖项的实例组件时,每次都会得到一个新组件。

  1. using(var scope = container.BeginLifetimeScope())
  2. {
  3. for(var i = 0; i < 100; i++)
  4. {
  5. // Every one of the 100 Worker instances
  6. // resolved in this loop will be brand new.
  7. var w = scope.Resolve<Worker>();
  8. w.DoWork();
  9. }
  10. }

2.Single Instance

单例,所有服务请求都将会返回同一个实例。

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

当您解析单个实例组件时,无论您请求何处,都始终获得相同的实例。

  1. // It's generally not good to resolve things from the
  2. // container directly, but for singleton demo purposes
  3. // we do...
  4. var root = container.Resolve<Worker>();
  5. // We can resolve the worker from any level of nested
  6. // lifetime scope, any number of times.
  7. using(var scope1 = container.BeginLifetimeScope())
  8. {
  9. for(var i = 0; i < 100; i++)
  10. {
  11. var w1 = scope1.Resolve<Worker>();
  12. using(var scope2 = scope1.BeginLifetimeScope())
  13. {
  14. var w2 = scope2.Resolve<Worker>();
  15. // root, w1, and w2 are always literally the
  16. // same object instance. It doesn't matter
  17. // which lifetime scope it's resolved from
  18. // or how many times.
  19. }
  20. }
  21. }

3.Instance Per Lifetime Scope

在一个嵌套语句块中,只会返回一个实例。

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

在解决每个生命周期实例作用域组件时,每个嵌套作用域将获得一个实例(例如,每个工作单元)。

  1. using(var scope1 = container.BeginLifetimeScope())
  2. {
  3. for(var i = 0; i < 100; i++)
  4. {
  5. // 每次从这里解析它
  6. // 你会得到相同的实例。
  7. var w1 = scope1.Resolve<Worker>();
  8. }
  9. }
  10. using(var scope2 = container.BeginLifetimeScope())
  11. {
  12. for(var i = 0; i < 100; i++)
  13. {
  14. //每次从这里解析它
  15. //每次解析都会得到一个同样的实例,但是这个示例和上面的循环的实例不是同一个
  16. var w2 = scope2.Resolve<Worker>();
  17. }
  18. }

4.Instance Per Matching Lifetime Scope

这与上面的'每个生命周期的实例范围'概念类似,但允许更精确地控制实例共享。

当您创建嵌套的生存期范围时,您可以“标记”或“命名”范围。具有每匹配生命周期范围的组件每个嵌套生命周期范围最多只有一个实例与给定名称匹配。这允许您创建一种“范围单例”,其中嵌套的生命周期范围可以在不声明全局共享实例的情况下共享某个组件的实例。

这对于特定于单个工作单元的对象是有用的,例如,一个HTTP请求,作为一个嵌套的生命周期可以创建每个工作单元。如果每个HTTP请求都创建一个嵌套的生命周期,那么每个具有每个生命周期范围的组件都将为每个HTTP请求创建一个实例。 (有关每个请求生命周期范围的更多信息。)

在大多数应用中,只有一层容器嵌套足以代表工作单元的范围。如果需要更多级别的嵌套(例如像global-> request-> transaction这样的东西),组件可以配置为使用标签在层次结构中的特定级别共享。

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

提供的标记值在启动时与生存期范围关联。 如果在没有正确命名的生命周期范围时尝试解析每个匹配生命周期范围的组件,则会得到一个异常。

  1. //使用标签创建生命周期
  2. using(var scope1 = container.BeginLifetimeScope("myrequest"))
  3. {
  4. for(var i = 0; i < 100; i++)
  5. {
  6. var w1 = scope1.Resolve<Worker>();
  7. using(var scope2 = scope1.BeginLifetimeScope())
  8. {
  9. var w2 = scope2.Resolve<Worker>();
  10. // w1和w2始终是同一个对象
  11.        //实例,因为该组件是每个匹配生命周期范围的,
  12.        //所以它实际上是一个单例
  13.        //命名范围
  14. }
  15. }
  16. }
  17. //使用标签创建另一个生命周期作用域
  18. using(var scope3 = container.BeginLifetimeScope("myrequest"))
  19. {
  20. for(var i = 0; i < 100; i++)
  21. {
  22. // w3 will be DIFFERENT than the worker resolved in the
  23. // earlier tagged lifetime scope.
  24. var w3 = scope3.Resolve<Worker>();
  25. using(var scope4 = scope3.BeginLifetimeScope())
  26. {
  27. var w4 = scope4.Resolve<Worker>();
  28. // w3和w4始终是同一个对象,因为
  29.        //他们在相同的标记范围内,但他们是
  30.        //与之前的w1,w2不一样。
  31. }
  32. }
  33. }
  34. //你无法解析每个匹配生命周期的组件
  35. //如果没有匹配的范围。
  36. using(var noTagScope = container.BeginLifetimeScope())
  37. {
  38. //因为这个范围没有,所以抛出一个异常
  39.    //有预期的标签,也没有任何父范围!
  40. var fail = noTagScope.Resolve<Worker>();
  41. }

5.Instance Per Request

某些应用程序类型自然适用于“请求”类型语义,例如ASP.NET Web Forms和MVC应用程序。 在这些应用程序类型中,有能力为每个请求提供一种“单例”。

通过提供众所周知的生命周期范围标记,注册便利方法以及针对常见应用程序类型的集成,每个请求的实例基于每个匹配生命周期范围的实例构建。 但在幕后,它仍然只是每个匹配生命周期范围的实例。

这意味着如果您尝试解析注册为每个请求实例但没有当前请求的组件,那么您将得到一个异常。

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

6.Instance Per 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. //消息处理程序本身以及
  4.    //解析依赖的ServiceForHandler服务
  5.    //在一个小小的生命周期范围内
  6.    // “范围。” 请注意解析一个拥有的<T>
  7.    //表示您负责处理。
  8. var h1 = scope.Resolve<Owned<MessageHandler>>();
  9. h1.Dispose();
  10. }

原文:http://autofaccn.readthedocs.io/en/latest/lifetime/instance-scope.html

Autofac容器对象实例的几种生命周期类型的更多相关文章

  1. Autofac学习之三种生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency

    InstancePerLifetimeScope:同一个Lifetime生成的对象是同一个实例 SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象:每次都用同一个对象: In ...

  2. Autofac学习之三种生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency 【转载】

    InstancePerLifetimeScope:同一个Lifetime生成的对象是同一个实例 SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象:每次都用同一个对象: In ...

  3. Vue 实例详解与生命周期

    Vue 实例详解与生命周期 Vue 的实例是 Vue 框架的入口,其实也就是前端的 ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进 ...

  4. Java对象在JVM中的生命周期

          当你通过new语句创建一个java对象时,JVM就会为这个对象分配一块内存空间,只要这个对象被引用变量引用了,那么这个对象就会一直驻留在内存中,否则,它就会结束生命周期,JVM会在合适的时 ...

  5. JAVA-JSP内置对象之session对象设置并获得session生命周期

    相关资料:<21天学通Java Web开发> session对象设置并获得session生命周期1.通过session对象的setMaxInactiveInterval()方法可以设置se ...

  6. ASP.NET Core :容器注入(二):生命周期作用域与对象释放

    //瞬时生命周期 ServiceCollection services = new ServiceCollection(); services.AddTransient<TestServiceI ...

  7. spring总结之一(spring开发步骤、bean对象的管理、bean生命周期)

    ###spring 1.概念:开源,轻量级,简化开发的企业级框架. 开源:免费,发展快. 轻量级:占内存小. 简化开发:通用的功能封装,提高程序员的开发效率.--------------------- ...

  8. 05-Vue入门系列之Vue实例详解与生命周期

    Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成.编译.挂着. ...

  9. 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期

    一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...

随机推荐

  1. 关于WPF中TextBox使用SelectAll无效的问题的解决办法

    1.首先保证你设置的SelectionBrush不是透明的颜色或者和背景色相同 2.在使用SelectAll之前要保证Textox以及获取到焦点. this.textbox.SelectionBrus ...

  2. Android SDK manager里面什么是必须下载的?

    最近公司来了位新同事,由于需要配置Android环境,但是在配置的时候却发现sdk很大,很占用空间,想复制给同事也觉得不方便,于是根据下面的图删除了一些不必要的api. 根据官方文档的描述SDK To ...

  3. php 接口与前端数据交互实现

    最近在做前后端数据交互的尝试,也跳了很多坑,使用的是php+bootstrap-table+js,把一些收获记录在这里,方便查询. 这个小项目,仅有3个文件,分别为: crud.html data.p ...

  4. Kotlin的参考资料

    参考资料和站点 http://kotlinlang.org/ 官方网站 https://github.com/JetBrains/kotlin/releases/tag/v1.0.6 下载compil ...

  5. (面试题)python面试题集锦-附答案

    1.一行代码实现1-100的和 sum_1_100 = sum(range(1, 101)) 2.如何在一个函数内修改全局变量的值 a = 100 def foo(): global a a = 30 ...

  6. 微信小程序中的循环遍历问题

    比如:如果在微信小程序中要遍历输出 0-9 的数,我们会使用for循环 ;i<;i++){ console.log(i); } 确实结果也是这样: 但是,如果我在循环时同时调用wx的api接口1 ...

  7. 初学ubuntu之文件权限权限

    今天接着做笔记,坚持学习下去. 文件权限修改命令,初学者看见这个命令之后总有些摸不着头脑,这命令里面用到了一些数字,我 自己也是,这次写一篇自己的认识.希望能够帮助到需要学习的人. 首先你可以通过 l ...

  8. web前端(3)—— html标签及web页面结构

    本节内容简单介绍下html都有哪些标签 还是百度首页,查看源代码看看: 我把源代码复制下来另存为html文件里: 注意:网页文件的后缀都是html或者htm 我这用的pycharm编辑器(Python ...

  9. 使用Navicat for Mysql连接mysql服务器

    使用Navicat for Mysql连接mysql服务器 在windows上用Navicat for Mysql 连接装在虚拟机Ubuntu上的mysql服务器时出现的问题的解决方案. Navica ...

  10. 实现Github和Coding仓库等Git服务托管更新

    如何使Github.Coding.Gitee 码云 同时发布更新,多个不同Git服务器之间同时管理部署发布提交 缘由 因为在Github上托管的静态页面访问加载速度较为缓慢,故想在Coding上再建一 ...