【问题标题】:Create new scope on asp.net core project using autofac使用 autofac 在 asp.net 核心项目上创建新范围
【发布时间】:2019-05-25 01:00:47
【问题描述】:

我正在使用带有 autofac 的 aspnet 核心。我有两个作为缓存的单例服务(从数据库中获取数据并缓存它们)。我需要创建一个新范围,以便声明为 InstancePerLifeTime 的 dbcontext 不会在两个单例服务之间共享(每个服务必须有它的自己的 dbcontext) 如何在 asp.net 核心中获取 IContainer? 我试图打电话给containerBuild.Build();,我得到了系统已经构建的容器的错误。

【问题讨论】:

    标签: c# .net asp.net-core .net-core autofac


    【解决方案1】:

    这不是生命周期范围的工作方式。

    如果您将某些内容注册为单例 (SingleInstance),它将从根生命周期范围内解析,而不是从子范围内解析。它的依赖关系_也将从根作用域(容器)而不是子作用域解析。

    This is walked through in fair detail on the documentation topic 'Captive Dependencies'.

    基本上,您不能有一个单例,它需要每个请求的实例或子生命周期范围依赖。你可以有一个单例,它需要每个依赖的实例(它只会被解析一次 - 从容器,而不是子范围 - 然后被持有);或者你可以有一个单例,它接受一个每生命周期实例的组件,并且使用的生命周期范围将是根容器,有效地从你正在消费的东西中创建一个单例。

    但是,您真正要问的问题是“如何在 ASP.NET Core 中获取容器”以及该问题的答案is also in the documentation, in the ASP.NET Core "Quick Start (Without ConfigureContainer)" section.

    • ConfigureServices 方法切换为返回IServiceProvider 而不是void
    • 自己构建容器并在您自己选择的某个位置保留对它的引用。
    • ConfigureSerivces末尾返回new AutofacServiceProvider(container)

    文档中有完整的代码示例。

    它不会帮助您解决更大的问题,但至少您可以获得容器并进行您想要的实验。

    【讨论】:

    • 感谢您的回复。是的,你是对的,单例是从根范围解析的。如果我有两个用于两个单例服务的数据库存储库,这意味着两个服务将使用相同的存储库实例(和 dbcontext),这将导致问题,因为上下文将在两个服务之间共享。我该如何克服这个问题?
    • 答案是停止让不能成为单例的东西成为单例。这是一个设计问题,而不是 Autofac 问题。
    • 我知道在大多数情况下单例使用起来非常糟糕,但不幸的是我无法避免它,因为我正在基于数据库构建缓存,因此我需要使用带有工作单元的数据库存储库
    • 您似乎也有三个答案可以涵盖您的问题,但答案大相径庭,因为问题非常广泛。考虑采取你在这里得到的东西,选择一个答案,然后创建一个新的、更有针对性的问题,其中包括 a minimal, verifiable, and complete example. 如果问题不完全清楚,人们真的很难提供帮助。
    • 我有一个最小的例子,但是太长了,不能在这里发布。
    【解决方案2】:

    我认为您不需要新的范围。据我所知dbcontext 的最佳实践是dbcontext-per-business operation。在 Web 应用程序的情况下,它是一个 Web 请求。

    在您的情况下,您可以将一些 IDbContextFactory(也是单例)传递给这些单例,并在需要时创建新的 DbContext 实例。

    【讨论】:

    • 这些服务使用在系统其他地方也使用的存储库。上下文工厂不起作用。
    【解决方案3】:

    您可以从构造函数解析ILifetimeScope 并调用其BeginLifetimeScope 方法。

    【讨论】:

    • 服务必须先启动,所以我需要在启动时进行。
    • 只要其他东西需要它,Autofac会先创建它
    • 如果您真的想在Startup 中获取IContainer,请告诉我您的托管模型(旧版WebHost 或通用Host
    • 如果是 WebHost,它接受 StartupConfigureServices,返回值类型为 IServiceProvider,然后您可以构建您的容器并使用来自包 Autofac.Extensions.DependencyInjectionAutofacServiceProvider 包装它并将其返回以供 ASP.NET Core 使用,这就是您可以在 Startup 中获取 IContainer 的地方。
    • 这正是我想要避免的。控制器需要它,我不想混合它们的 dbcontexts。 WebHpst 或通用主机。你能解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-24
    相关资源
    最近更新 更多