【问题标题】:How to determine which lifestyle to use in Simple Injector如何确定在 Simple Injector 中使用哪种生活方式
【发布时间】:2018-08-29 13:06:42
【问题描述】:

我的应用程序使用实体框架。由于我希望我的DbContext 在单个请求中被重用,因此我将其注册为Lifestyle.Scoped,如下所示:

container.Register<MyDbContext>(Lifestyle.Scoped);

其他类得到这个MyDbContext 注入。例如,请参阅以下存储库:

ApplicationsRepository 是:

public class ApplicationsRepository : IApplicationsRepository
{
    private readonly MyDbContext _dbContext;

    public ApplicationsRepository(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Save()
    {
        _dbContext.Save();
    }

    public Application GetByName(string appName)
    {
        var dbApplication = _dbContext.APPLICATIONS.FirstOrDefault(a => a.NAME == appName);

        return ApplicationMapper.MapApplicationFromAPPLICATIONS(dbApplication);
    }
}

但是还有无数其他类依赖于MyDbContext。其他类可能不直接依赖于MyDbContext,但会注入一个依赖于MyDbContext 的类。

我的问题是:我应该对这些课程使用什么样的生活方式管理以及如何实施?

【问题讨论】:

  • 您的问题中有很多细节似乎与您的问题无关。如果我正确解释了您的问题,您的问题是:“我如何确定我需要哪种生活方式来上课?”。对吗?
  • 是的,没错!
  • 抱歉请求不正确。是现在吗??
  • 请注意,您应该在抽象上实现IDisposable。此外,ApplicationsRepository 应该处置 MyDbContext,因为 1. Simple Injector 已经这样做了,并且 2. 存储库不知道处置该依赖项是否安全。从您的类中删除该处置逻辑会大大简化它们。欲了解更多信息,请阅读:stackoverflow.com/questions/30283564/…

标签: c# dependency-injection ioc-container simple-injector


【解决方案1】:

有 3 种基本生活方式可供选择,Transient、Scoped 和 Singleton,正如您在阅读 this 时已经了解的那样。

为特定组件选择哪种生活方式取决于几个因素:

  • 组件是否可以跨请求/线程安全使用
  • 组件是否包含需要跨线程共享的状态
  • 组件依赖项的生活方式。

首先,您的组件所需的生活方式是您需要根据该组件的设计方式做出的选择。有些组件根本无法重用,应始终在请求时重新创建。这通常适用于框架类型,例如 MVC 控制器。虽然每个请求通常有一个控制器,但可以请求其他控制器,这需要创建新实例。这相当于 Transient 的生活方式。

您注册的其他组件或类需要重用。实体框架的DbContext 等工作单元实现通常需要在完整请求期间重复使用。您可以阅读有关为什么要重用 DbContext here 的详细讨论。这相当于 Scoped 生活方式。

其他组件是完全无状态或不可变的,可以由应用程序中的所有线程并行重用,而不会遇到任何麻烦。其他组件可能是有状态的或可变的,但在设计时考虑了线程安全。他们可能会实现需要更新的应用程序范围的缓存,并且对组件的访问受到锁的保护。这意味着您只有一个实例在整个应用程序中重用。这相当于 Singleton 的生活方式。

依赖关系使组件的生活方式选择变得复杂,因为组件的生活方式应该永远长于它的任何依赖关系。如果不遵守此规则,则会导致 Captive DependenciesLifestyle Mismatches(Simple Injector 调用它们)。

这意味着即使您确定一个组件有资格成为单例,它也只能与它的最短依赖关系一样长。换句话说,如果组件具有 Scoped Dependency,那么它本身只能是 Scoped 或 Transient。 Simple Injector will detect 如果您配置错误。

然而,这确实意味着您为组件所做的选择确实会将调用堆栈向上传播到组件的使用者。

通常,这会导致应用程序对象图中的叶组件是 Scoped 和 Singleton 的结构,而根类型是 Transients。如果您以这种方式构建您的对象图,您将遵循Closure Composition Model

还有一个替代品DI Composition Model,它被称为Ambient Composition Model。在练习此模型时,您在大多数情况下将状态排除在组件之外,而是将状态存储在由Composition Root 控制的环境状态中。两种合成模型都有自己的advantages and disadvantages

【讨论】:

  • 最后,我使用了 SimpleInjector.Integration.Wcf,我注册了我的 wcf,我将我的容器注册为 container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();和 MyDbContext 作为 Lifestyle.Scoped。我希望它是正确的。谢谢
猜你喜欢
  • 2017-08-16
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
相关资源
最近更新 更多