我们已经创建了一个单例对象( SsoSettingsProvider ),其中我们使用生活方式PerWebRequest注入对象(在我们的示例中,它是WCF客户端的 IReservationService )。在构造函数中,我们使用此对象来获取一些数据,并将这些数据放在私有字段中。
public class SsoSettingsProvider : ISsoSettingsProvider
{
readonly LogonSettings _logonSettings;
public SsoSettingsProvider(IReservationService reservationService)
{
_logonSettings = reservationService.GetSSOSettings();
}
}
如果我们看一下Castle Windsor可能存在的生活方式不匹配,那就说:
“具有生活方式的组件'SsoSettingsProvider / ISsoSettingsProvider' Singleton依赖于'后期绑定IReservationService'与生活方式 PerWebRequest通常不需要这种依赖,也可能 导致各种各样的错误。“
这个信息说只有可能,但在这种情况下我认为这不是问题,因为注入的对象没有在字段中引用,所以它可以被垃圾收集。我是对的吗?
答案 0 :(得分:1)
在这种情况下,我认为这不是问题,因为注入的对象没有在字段中引用,因此可以进行垃圾回收。我是对的吗?
Castle Windsor警告Captive Dependencies。主要问题不是实例不是垃圾收集,而是一个类将重用一个不打算重用的实例。
简单示例是将DbContext
注入到配置为singleton的类中。虽然这会导致DbContext
保持活着状态,直到其单身消费者超出范围(通常是应用程序结束时)。但是,DbContext
不应在多个请求中重复使用。首先,因为它根本不是线程安全的。最重要的是,它很快就会变得陈旧,导致它返回缓存的数据,而不是重新查询数据库。
出于这个原因,我们register DbContext typically as Scoped。然而,这确实意味着它的所有消费者应该与DbContext
一样长寿,以防止它破坏应用程序。这就是Castle所警告的。
但是,在您的情况下,您不会将IReservationService
存储到SsoSettingsProvider
的私有字段中。这仍然是一个问题,因为期望IReservationService
返回的对象不会比IReservationService
更长(否则IReservationService
将被注册为Singleton)是合理的。从SsoSettingsProvider
的角度来看,它无法知道存储LogonSettings
是否安全,根本不存储会好得多。
除此之外,如表达式here,注入构造函数根本不应使用它们的依赖项。这会导致对象组合缓慢且不可靠。
所以即使你可能已经分析了你的设计,并且确信这在你的特定情况下有效,我建议你做以下事情之一:
IReservationService
存储为SsoSettingsProvider
中的私有字段,并仅在调用GetSSOSettings
个成员之一时调用SsoSettingsProvider
并阻止存储LogonSettings
。这会强制您制作SsoSettingsProvider
作用域或IReservationService
单例。 IReservationService
是否可以是单身人士只是你能找到的东西。SsoSettingsProvider
仅对LogonSettings
感兴趣,而LogonSettings
是一个在应用程序启动后不会更改的常量值,则应直接注入LogonSettings
SsoSettingsProvider
的构造函数。这简化了SsoSettingsProvider
并将LogonSettings
加载到Composition Root。