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

原文地址: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. MVC还是MVVM?或许VMVC更适合WinForm客户端

    最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』.相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的 ...

  2. ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id

    出现场景:当点击"分类"再返回"首页"时,发生error退出   BUG描述:Caused by: java.lang.IllegalArgumentExcep ...

  3. Tomcat 部署我的第一个程序

    idea 生成war包.先双击clean,再双击package.生成成功之后就会产生war包. 第二步:将生成好的war文件复制到tomcat文件夹下. 第三步:配置tomcat的server.xml ...

  4. shell之sort命令

    1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. [rocrocket@rocrocket progr ...

  5. CYQ.Data V5 从入门到放弃ORM系列:教程 - MProc类使用

    MProc介绍 MProc:是一个用于执行SQL或存储过程的数据库操作类,它轻量高性能地类似于Dapper. MProc:它出现的场景很少,因为MAction自身就能处理掉90%-100%的数据操作( ...

  6. ES6 箭头函数中的 this?你可能想多了(翻译)

    箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...

  7. Angular2笔记:NgModule

    Angular的模块的目的是用来组织app的逻辑结构. 在ng中使用@NgModule修饰的class就被认为是一个ng module.NgModule可以管理模块内部的Components.Dire ...

  8. 转 10 个最佳的 Node.js 的 MVC 框架

    10 个最佳的 Node.js 的 MVC 框架 oschina 发布于: 2014年02月24日 (33评) 分享到:    收藏 +322 Node.js 是一个基于Chrome JavaScri ...

  9. JavaScript继承的模拟实现

    我们都知道,在JavaScript中只能模拟实现OO中的"类",也就意味着,在JavaScript中没有类的继承.我们也只能通过在原对象里添加或改写属性来模拟实现. 先定义一个父类 ...

  10. 使用xUnit,EF,Effort和ABP进行单元测试(C#)

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 介绍 创建测试项目 准备测试基类 创建第一个测试 测试异常 在测试中使用仓储 测试异步方法 小结 介绍 在这篇博客中,我 ...