C# Autofac-InstancePerHttpRequest vs InstancePerLifetimeScope

C# Autofac-InstancePerHttpRequest vs InstancePerLifetimeScope,c#,asp.net-mvc-3,dependency-injection,autofac,C#,Asp.net Mvc 3,Dependency Injection,Autofac,这两个范围有什么区别 我正在每个层(存储库、服务、MVC应用程序)中构建模块,但为了拥有InstancePerHttpRequest,您需要Autofac.MVC程序集 我应该在存储库和服务层中使用哪个作用域?在Autofac中,每个生存期作用域是使用嵌套生存期创建自定义作用域的一种通用方法 使用InstancePerLifetimeScope为您提供了每个请求范围,这为单个请求增加了组件生存期,并在内部为此组件使用InstancePerLifetimeScrope 在任何需要的地方使用Inst

这两个范围有什么区别

我正在每个层(存储库、服务、MVC应用程序)中构建
模块
,但为了拥有
InstancePerHttpRequest
,您需要Autofac.MVC程序集

我应该在存储库和服务层中使用哪个作用域?

在Autofac中,每个生存期作用域是使用嵌套生存期创建自定义作用域的一种通用方法

使用
InstancePerLifetimeScope
为您提供了每个请求范围,这为单个请求增加了组件生存期,并在内部为此组件使用
InstancePerLifetimeScrope


在任何需要的地方使用InstancePerLifetimeScope
,或者,如果在服务层中引用
Autofac.Integration.Mvc
程序集有问题,请在每次请求开始时手动创建嵌套作用域,并使用
InstancePerLifetimeScope

在应用程序中,唯一完全能够决定对象生存期的位置是组成根

在这种情况下,您有一个冲突——您有一个通用模块,它不应该访问MVC集成提供的扩展方法——但是您需要访问它,以便正确管理生命周期。在这种情况下,如果您的模块可以提供一个合理的默认值,比如
InstancePerLifetimeScope
,那么这就是我在模块级别所做的。然后,让合成根覆盖该行为。在这种情况下,合成根目录会将生存期更改为
instanceperhtprequest
。由于上次注册将覆盖以前的注册,因此您应该处于良好状态

我实际上已经不再创建与包含给定层的程序集共存的模块,原因有两个:

  • 它引入了对Autofac的依赖性,我不希望它出现在我的合成根目录下
  • 这表明模块知道应该如何管理其生命周期,这通常是不正确的。如果有,为什么不提供一个工厂或其他类来提供这种生命周期管理呢

  • 取而代之的是(在足够大的项目中),我在组合根级别创建模块,因为在这个级别,我清楚地知道它们应该如何连接在一起。有时,我会创建一个包含模块的
    Ioc
    程序集,该程序集充当默认的合成根,但这通常在“真实”合成根处被覆盖(例如,拉入
    Ioc
    程序集的控制台或MVC应用程序).

    InstancePerHttpRequest
    InstancePerApiRequest
    基本上做了相同的事情-对于每个离散的web请求,您都会得到一个服务实例。我将使用
    instanceperhtprequest
    来回答其余的问题,但请记住,这两个问题是可以互换的

    InstancePerLifetimeScope
    表示将为请求您的服务的每个生存期作用域创建一个新的服务实例。每个web请求都有自己的新生命周期范围,因此在实践中,这两个请求通常会做完全相同的事情

    唯一真正的区别是,如果您在
    instanceperhtprequest
    下注册了一个服务,并且您从另一个注册为
    SingleInstance
    的服务请求其中一个服务。在这种情况下:

    • SingleInstance
      组件位于根范围内
    • instanceperhtprequest
      组件位于名为“AutofacWebRequest”的作用域中,该作用域是根作用域的子作用域
    Autofac不允许从子作用域解析-因此本质上,
    SingleInstance
    服务找不到
    instanceperhtprequest
    服务

    但是,如果在此场景中您使用了
    InstancePerLifetimeScope
    (而不是
    InstancePerHttpRequest
    ),那么您的服务将很好地解决问题

    我写了一篇相当详尽的文章,其中包含可下载的代码,试图详细解释所有这些-。引述文章:

    这里一个常见的误解是,在WebAPI应用程序中向InstancePerLifetimeScope注册组件意味着组件存在于web请求的范围内,即“生存期”指的是“web请求的生存期”。正如你在这里看到的,这是错误的

    组件的生存期取决于解析的范围。

    由于SingletonResolvable从根作用域解析其令牌,因此该令牌实例位于根作用域中,而不是web请求的作用域中。我以前说过,但我要再说一遍:这个令牌将一直存在,直到整个应用程序被处理(例如,IIS工作进程被回收)。任何从根作用域请求ScopeToken的操作都将获得对该标记的引用


    希望能有所帮助-我理解这个问题现在已经很老了,但是它仍然非常相关

    然后我应该在我的服务和存储库模块中使用
    InstancePerLifetimeScope
    ,在我的全局模块中使用
    InstancePerHttpRequest
    。当然,如果您不是手动创建嵌套范围,则每个生存期范围将是一个单一范围。所以,您最好在任何地方使用请求作用域,或者在每个请求的开头手动创建嵌套作用域。所以我需要在我的服务和存储库模块中使用InstancePerHttpRequest?您是否有一个创建范围的示例,该范围仅适用于我可以实现的每个请求?谢谢对卡莱布在回答中提出的另一个好建议是,将所有的Autofac模块转移到MVC项目中,然后在几个层次上消除不必要的Autofac依赖关系和生命周期逻辑,最好在应用程序入口的一个地方