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

原文地址: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 组件的实例范围的更多相关文章

  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. javascript arguments(转)

    什么是arguments arguments 是是JavaScript里的一个内置对象,它很古怪,也经常被人所忽视,但实际上是很重要的.所有主要的js函数库都利用了arguments对象.所以agru ...

  2. Windows Server 2008 R2常规安全设置及基本安全策略

    这篇文章主要介绍了Windows Web Server 2008 R2服务器简单安全设置,需要的朋友可以参考下 用的腾讯云最早选购的时候悲催的只有Windows Server 2008 R2的系统,原 ...

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

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

  4. ASP.NET MVC Model验证(一)

    ASP.NET MVC Model验证(一) 前言 前面对于Model绑定部分作了大概的介绍,从这章开始就进入Model验证部分了,这个实际上是一个系列的Model的绑定往往都是伴随着验证的.也会在后 ...

  5. [Mahout] 完整部署过程

    概述        Mahout底层依赖Hadoop,部署Mahout过程中最困难的就是Hadoop的部署      本文假设用户本身没有进行Hadoop的部署,记述部署Mahout的过程       ...

  6. 将一句话里的单词进行倒置,标点符号不倒换。比如将“I come from Shanghai.”倒换后变为“Shanghai. from come I”

    string str = "I come from Shanghai."; //根据空格切割 string[] strS = str.Split(' '); string temp ...

  7. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  8. 网站使用https协议

    了解https HTTPS 是以安全为目标的 HTTP 通道,即 HTTP 下加入 SSL 加密层.HTTPS 不同于 HTTP 的端口,HTTP默认端口为80,HTTPS默认端口为443. SSL ...

  9. datepickerx设置默认日期

    datepicher插件是jQuery UI的一个插件,它提供一个日期弹出窗口(或直接显示在页面),供用户选择日期.在Web开发中,总会遇到需要用户输入日期的情况.一般都是提供一个text类型的inp ...

  10. 【译】Unity3D Shader 新手教程(3/6) —— 更加真实的积雪

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你满足以下条件,我建议你阅读这篇教程: 你想知道如何在表面着色器中进行混色(blend colour) 你想实 ...