使用 Microsoft.Extensions.DependencyInjection 创建子容器(或隔离范围)的最佳策略

2024-02-20

在我的 AspNetCore 应用程序中,我处理从队列到达的消息。为了处理消息,我需要解析一些服务。其中一些服务依赖于ITenantId,我使用收到的消息中的信息进行绑定。为了解决这个问题,消息的处理从创建一个子容器开始,然后我用它来创建一个服务范围 https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicescope?view=dotnet-plat-ext-3.1我从中解决了所有需要的依赖关系。

消息可以并行处理,因此作用域必须相互隔离。

我可以看到创建子容器的方法,但我不确定哪种方法在性能、内存更改等方面最好:

选项 A:每次消息到达时,将 IServiceCollection 克隆到新的 ServiceCollection 中,然后重新绑定ITenantId在克隆实例上。

选项 B:当程序启动时,创建 IServiceCollection 的不可变副本(使用ImmutableList<ServiceDescriptor> or ImmutableArray<ServiceDescriptor>)。每次消息到达时,替换ITenantId(导致一个新的实例ImmutableList<ServiceDescriptor>)并致电CreateScope()在新的不可变实例上。

我不喜欢选项 A 的一点是,每次消息到达时都需要克隆整个服务集合。我不确定选项 B 中的不可变集合是否以更智能的方式处理这个问题?


这两个选项都会导致为每个传入消息创建一个新的容器实例。尽管这允许每条消息在完全隔离的气泡中运行,但这对应用程序的性能和内存使用有严重影响。创建容器实例的成本很高,并且第一次(每个容器)解析注册实例会导致生成表达式树、编译委托以及 JIT 编译它们。这甚至可能导致内存泄漏。

此外,这还意味着任何注册的单例类都将具有与任何作用域类相同的生命周期。状态无法再共享。

因此,我建议选择 3:

  • 只使用一个Container实例并且不调用BuildProvider不止一次
  • 创建一个ITenantId允许设置的实现Id实例化后
  • 将该实现注册为Scoped
  • 在每一个新的开始IServiceScope,解析该实现并设置其 id。

这可能如下所示:

// Code
class TenentIdImpl : ITenantId
{
    public Guid Id { get; set; } // settable
}

// Startup:
services.AddScoped<TenentIdImpl>();
services.AddScoped<ITenantId>(c => c.GetRequiredService<TenantIdImpl>());

// In message pipeline
using (var scope = provider.CreateScope())
{
    var tenant = scope.ServiceProvider.GetRequiredService<TenantIdImpl>();
    tenant.Id = messageEnvelope.TenantId;

    var handler =
        scope.ServiceProvider.GetRequiredService<IMessageHandler<TMessage>>();

    handler.Handle(messageEnvelope.Message);
}

我在博客中解释了这个特定的模型,您将状态存储在对象图中,我将其称为闭包组合模型 https://blogs.cuttingedge.it/steven/posts/2019/closure-composition-model/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Microsoft.Extensions.DependencyInjection 创建子容器(或隔离范围)的最佳策略 的相关文章

  • 如何更改.net core的URL后缀?

    我怎样才能有以下路线 http localhost 4413 abc 以及以下路线 http localhost 4413 abc html 两者都返回相同的控制器方法 使用 NET Core MVC 听起来您想要两个后缀来达到相同的控制器
  • 使用 asp.net mvc 4 的简单注入器,从另一个程序集加载控制器

    我正在开发一个 asp net mvc 4 站点 使用 Simple Injector 作为 Ioc 工具 这将是一个可插拔的架构 某些控制器和视图位于另一个程序集中 另一个 mvc4 应用程序 Plugin Web dll 从主应用程序中
  • 设置惰性静态变量首先初始化然后分配?

    我意识到static变量是隐式的lazy 这真的很棒 执行以下操作在第一次调用之前不会创建实例 static var test Test 但是 将一个新实例分配给static变量初始化原始实例 然后分配新实例 这对我来说很麻烦 SomeTy
  • 私有只读接口 - 它是多余的吗?

    我在我的项目中使用 IoC 和 DI 但是我想知道以下是否是一个好的做法 private readonly IMyService myservice 作为服务使用者的类内的字段 该字段在构造函数中设置 我确信我在某处见过这个并且我已经注意到
  • system.web.http.HttpError 的.Net 标准/核心版本

    从 net Framework 迁移到 net Standard Core 时 我遇到了 HttpError 类 除了兼容性垫片之外 我在 net core standard 中找不到任何等效项 这只是一个临时解决方案 不知道官方有没有替代
  • 何时使用接口,何时使用高阶函数?

    给定一个具有以下层的 ASP NET MVC 应用程序 UI 视图 CSS Javascript 等 控制器 服务 包含业务逻辑和数据访问 没有单独的数据访问层的原因是我正在使用 SQL 类型提供程序 以下代码可能不起作用 因为它只是原始草
  • 使用 EnumeratorCancellation 返回 AsyncEnumerable 或循环 WithCancellation 有什么区别

    我有以下方法从 http 流读取 csv 文档 public async IAsyncEnumerable
  • EF Core 第二级 thenIninclude 错误

    假设首先有这些模型 Method有一个OriginalCode OriginalCode那有很多Mutants Mutant那有很多ParseSubTrees 现在当查询时Method我希望加载另一个 所以我有以下内容 Method tar
  • 我们需要依赖注入的接口吗?

    我有一个 ASP NET Core 应用程序 该应用程序有一些帮助程序类可以完成一些工作 每个类都有不同的签名方法 我在网上看到很多 net core 示例 它们为每个类创建接口 然后向 DI 框架注册类型 例如 public interf
  • Docker .Net 6 错误程序不包含适合入口点的静态“Main”方法

    我正在尝试构建我的 docker 映像 但收到此错误 错误CS5001 程序不包含适合入口点的静态 Main 方法 6GAG WebApi 6GAG WebApi csproj 我的 1 个解决方案中有 3 个项目 1 webapi 1个前
  • ASPNETCoreModule 未与 .NET Core SDK 一起安装

    我安装了VS 2017随着 NET Core SDK在Windows 10上 但它没有安装ASPNETCoreModule如下图2所示 我想 NET Core SDK应该隐式安装它 并且不必单独安装它 NOTE 我正在尝试将我的 asp n
  • TestContext.DataRow["MyColumnName"] 的替代品是什么

    在 Net Core 单元测试项目中使用 MSTest 我正在尝试使用 csv 数据源来提供测试方法的数据 以前 我会在 Net Framework 测试项目中使用如下所示的内容 DataSource Microsoft VisualStu
  • 在ConfigureServices中注入依赖

    在我的 ASP Net Core 应用程序中 我需要在以下位置注入一些依赖项 在我的例子中是一个存储库 ConfigureServices method 问题是该方法不允许使用多个参数来注入依赖项 该怎么办呢 这是我的代码 public v
  • 框架时代的封装

    在我以前的 C 工作中 我们总是非常小心地封装成员变量 并且仅在绝对必要时才将它们作为属性公开 我们有非常具体的构造函数来确保您在使用对象之前完全构造了该对象 如今 使用 ORM 框架 依赖注入 序列化等 似乎您最好只依赖默认构造函数并在属
  • 使用 Novell LDAP 对 .NET Core 中的 AD 进行页面 LDAP 查询

    我正在使用 Novell LDAP 库从 NET 代码应用程序查询 Active Directory 大多数查询都会成功 但有些查询会返回 1000 多个结果 而 AD 服务器会拒绝这些结果 因此 我试图找出如何使用 Novell 的库来分
  • 在docker中使用MySQL数据库设置aspnetcore

    我正在尝试设置一个 docker compose 文件 其中包含 asp net core mysql 数据库和 phpmyadmin 的容器 设置我的 mysql 服务器没有问题 我可以使用 phpmyadmin 访问它 我的 asp n
  • 在project.json .Net Core中本地管理nuget

    我不想依赖 nuget 服务来下载依赖项 我想在我的 Net Core 应用程序中本地下载并使用 nuget 包 是否可以 方法与之前相同 打开您的NuGet config https docs nuget org consume nuge
  • UnitTest HttpResponse WriteAsync 和 CopyToAsync

    我想对下一个方法进行单元测试 public static async Task SetResponseBody HttpResponse response string message var originalResponseBody re
  • TargetFramework 与 TargetFrameworks(复数)

    In the csproj我的 NET Core 项目中的文件中 默认有以下 3 行
  • .NET 实体框架核心

    我已经阅读了过去两年中发布的几乎所有有关 EF 的其他问题 我下载其他软件包没有任何问题 只是实体框架不会为我安装 我什至尝试安装最新版本的 Nuget 并在我的项目目录中使用它的工具来恢复包 之后 我将这一行添加到我的 csproj 中

随机推荐