为什么 Microsoft 警告不要使用 PerRequestLifetimeManager

Omi*_*mir 0 c# asp.net asp.net-mvc entity-framework unity-container

https://msdn.microsoft.com/en-us/library/microsoft.practices.unity.perrequestlifetimemanager(v=pandp.30).aspx指出:

尽管 PerRequestLifetimeManager 生命周期管理器工作正常,并且可以帮助处理HTTP 请求范围内的有状态或线程不安全的依赖项,但在可以避免的情况下使用它通常不是一个好主意,因为它通常会导致错误实践或在使用不当时难以在最终用户的应用程序代码中发现错误。建议您注册的依赖项是无状态的,如果需要在 HTTP 请求的生命周期内在多个对象之间共享公共状态,那么您可以拥有一个无状态服务,该服务使用 Items 集合显式存储和检索此状态当前对象。

警告指的是哪种错误或不良做法?一个人会如何错误地使用它?- 不幸的是,警告不是很具体,因此很难应用于现实世界。此外,我不清楚在这种情况下有状态意味着什么。

恕我直言,使用 PerRequestLifetimeManager 的典型场景是某种数据库连接(例如 DbContext)或类似的。

Sco*_*nen 5

它的目的是每个请求只实例化一个实例,这可以(例如)防止在单个请求过程中进行冗余操作和查找。

危险在于,如果有人认为创建的对象是在请求期间存储状态的好地方。依赖注入的想法是一个类接收一个依赖项(通常是一个接口)并且除了实现该接口之外根本不“知道”任何关于它的信息。

但是有人可能会推断,如果对象将在请求的整个生命周期中持续存在,那么它是在请求期间维护状态的好地方。因此,他们创建了一个复杂的场景,其中一个类接收依赖项,在其中存储一些信息(例如设置属性),然后另一个类接收相同的依赖项并期望读取该属性。

现在依赖注入(解耦)的目的已经落空,因为类已经内置了关于依赖的生命周期是什么的假设,甚至可能包括关于其他类已经或将要对那个对象的状态做什么的假设。这会造成混乱,类之间的交互很难被察觉——甚至是隐藏的——因此很容易被打破。

假设有人确定该依赖项的生活方式应该是暂时的,而不是每个 Web 请求。突然间,依赖它的那些类的所有行为都停止按预期工作。所以开发人员查看这些类,发现没有任何变化。发生了什么?这些类之间的交互起初是很难看到的,所以一旦中断,问题就很难发现。如果这种依赖的生活方式改变有一些正当的理由,那么问题将更难解决。

如果我们需要在请求期间存储状态,那么我们应该把它放在“正常”的地方,比如HttpContext. 仍然存在一些令人困惑的实践和错误的空间,但至少我们知道HttpContextis(根据定义)将与特定请求相关联。