Castle Windsor PerWebRequest对象在Singleton对象中注入,而不在字段

时间:2017-08-29 08:10:20

标签: c# asp.net-web-api dependency-injection castle-windsor castle-windsor-3

我们已经创建了一个单例对象( 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通常不需要这种依赖,也可能   导致各种各样的错误。“

这个信息说只有可能,但在这种情况下我认为这不是问题,因为注入的对象没有在字段中引用,所以它可以被垃圾收集。我是对的吗?

1 个答案:

答案 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。