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

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

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

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

1.Instance Per Dependency

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

var builder = new ContainerBuilder();

// This...
builder.RegisterType<Worker>(); // 此句代码的效果同上
builder.RegisterType<Worker>().InstancePerDependency();

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

using(var scope = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
// Every one of the 100 Worker instances
// resolved in this loop will be brand new.
var w = scope.Resolve<Worker>();
w.DoWork();
}
}

2.Single Instance

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

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

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

// It's generally not good to resolve things from the
// container directly, but for singleton demo purposes
// we do...
var root = container.Resolve<Worker>(); // We can resolve the worker from any level of nested
// lifetime scope, any number of times.
using(var scope1 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>(); // root, w1, and w2 are always literally the
// same object instance. It doesn't matter
// which lifetime scope it's resolved from
// or how many times.
}
}
}

3.Instance Per Lifetime Scope

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

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

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

using(var scope1 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
// 每次从这里解析它
// 你会得到相同的实例。
var w1 = scope1.Resolve<Worker>();
}
} using(var scope2 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
//每次从这里解析它
//每次解析都会得到一个同样的实例,但是这个示例和上面的循环的实例不是同一个
var w2 = scope2.Resolve<Worker>();
}
}

4.Instance Per Matching Lifetime Scope

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

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

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

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

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

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

//使用标签创建生命周期
using(var scope1 = container.BeginLifetimeScope("myrequest"))
{
for(var i = 0; i < 100; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>(); // w1和w2始终是同一个对象
       //实例,因为该组件是每个匹配生命周期范围的,
       //所以它实际上是一个单例
       //命名范围
}
}
} //使用标签创建另一个生命周期作用域
using(var scope3 = container.BeginLifetimeScope("myrequest"))
{
for(var i = 0; i < 100; i++)
{
// w3 will be DIFFERENT than the worker resolved in the
// earlier tagged lifetime scope.
var w3 = scope3.Resolve<Worker>();
using(var scope4 = scope3.BeginLifetimeScope())
{
var w4 = scope4.Resolve<Worker>(); // w3和w4始终是同一个对象,因为
       //他们在相同的标记范围内,但他们是
       //与之前的w1,w2不一样。
}
}
}
//你无法解析每个匹配生命周期的组件
//如果没有匹配的范围。
using(var noTagScope = container.BeginLifetimeScope())
{
//因为这个范围没有,所以抛出一个异常
   //有预期的标签,也没有任何父范围!
var fail = noTagScope.Resolve<Worker>();
}

5.Instance Per Request

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

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

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

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

6.Instance Per Owned

拥有的隐式关系类型创建新的嵌套生命周期作用域。 可以使用每个拥有实例的注册来将依赖关系限定到拥有的实例。

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

在这个例子中,ServiceForHandler服务将被限制在拥有的MessageHandler实例的生命周期中。

using(var scope = container.BeginLifetimeScope())
{
//消息处理程序本身以及
   //解析依赖的ServiceForHandler服务
   //在一个小小的生命周期范围内
   // “范围。” 请注意解析一个拥有的<T>
   //表示您负责处理。
var h1 = scope.Resolve<Owned<MessageHandler>>();
h1.Dispose();
}

原文: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. Flutter 布局(五)- LimitedBox、Offstage、OverflowBox、SizedBox详解

    本文主要介绍Flutter布局中的LimitedBox.Offstage.OverflowBox.SizedBox四种控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析. 1. Limited ...

  2. 方向键控制圆球运动(简易)(js)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)

    Big Number 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1212 ——每天在线,欢迎留言谈论. 题目大意: 给你两个数 n1,n2.其中n1 ...

  4. github仓库本地创建上传远程仓库

    1.现在githubu创建自己心意的仓库. 2.然后再本地创建文件夹 echo"#  (远程仓库的名字) >>README.md git add README.md git co ...

  5. Solr5.5高级应用(基于tomcat9)

    一.配置solr 1.配置 注意:要是想放到其它路径下,可以修改此路径下的web.xml配置文件 修改内容如下: <!-- 将solrhome的绝对路径写入env-entry-value --& ...

  6. 如何解决远程连接mysql出现Can’t connect to MySQL server on (111 “Connection refused”)的问题

    如何解决远程连接mysql出现Can’t connect to MySQL server on (111 “Connection refused”)的问题 开放Mysql的远程连接 在服务器上登录my ...

  7. Python的变量以及类型

    1.程序是用来处理数据的,变量就是用来存储数据的  num1 = 100 2.为了更充分的利用内存空间以及更有效率的管理内存,变量是有不同的类型 3.怎样知道一个变量的类型呢? 3.1 在python ...

  8. 关于cisco日志的配置

    实例: en conf t clock timezone GMT+8  #设置北京时间 exit clock set HH:MM:SS DAY MONTH YEAR  #设置当前时间 service ...

  9. spring拦截器(interceptor)简介

    1. 拦截器用途 (1)拦截未登录用户直接访问某些链接 (2)拦截日志信息 (3)拦截非法攻击,比如sql注入 2. 涉及jar.类 (1)spring-webmvc.jar (2)HandlerIn ...

  10. js获取当前页面url网址信息

    js如何准确获取当前页面url网址信息 在WEB开发中,时常会用到javascript来获取当前页面的url网址信息,在这里是我的一些获取url信息的小总结. 下面我们举例一个URL,然后获得它的各个 ...