We have created a singleton object (SsoSettingsProvider ) in which we inject object with lifestyle PerWebRequest (IReservationService in our example it is WCF client). In constructor we use this object to get some data and we place this data in a private field.
public class SsoSettingsProvider : ISsoSettingsProvider
{
readonly LogonSettings _logonSettings;
public SsoSettingsProvider(IReservationService reservationService)
{
_logonSettings = reservationService.GetSSOSettings();
}
}
If we look at possible lifestyle mismatches in Castle Windsor it says:
"Component 'SsoSettingsProvider / ISsoSettingsProvider' with lifestyle Singleton depends on 'late bound IReservationService' with lifestyle PerWebRequest This kind of dependency is usually not desired and may lead to various kinds of bugs."
This info says that there is only possibility, but in this case i think it is not a problem because injected object is not referenced in a field so it can be garbage collected. am i right ?
Castle Windsor is warning about Captive Dependencies. The main problem is not so much that instances aren’t garbage collected, but a class will reuse an instance that is not intended for reuse.
Simple example is when you inject a
DbContextinto a class that is configured as singleton. Although this will result in theDbContextbeing held alive until its singleton consumer goes out of scope (which typically is when the application ends). ADbContexthowever should not be reused over multiple requests. For one, because it simply isn't thread-safe. On top of that, it gets stale very soon, which causes it to return cached data, instead of re-querying the database.For this reason we register DbContext typically as Scoped. This does mean however that all its consumers should live at most as long as the
DbContext, to prevent it from breaking the application. This is what Castle is warning about.In your case however you don't store the
IReservationServiceinto a private field ofSsoSettingsProvider. This would still be a problem, because it would be reasonable to expect that the objects thatIReservationServicereturns do not outlive theIReservationService(otherwiseIReservationServicewould be registered as Singleton). Since from the perspective ofSsoSettingsProvider, there is no way it could know whether or not it is safe to storeLogonSettings, it is much better to not store it at all.On top of that, as expressed here, injection constructors should not use their dependencies at all. This leads to slow and unreliable object composition.
So even though you might have analyzed your design and know for sure that this works in your particular case, I would suggest you doing one of the following things:
IReservationServiceas private field inSsoSettingsProviderand callGetSSOSettingsonly when one ofSsoSettingsProvider's members is called and prevent storingLogonSettings. This forces you to make eitherSsoSettingsProviderscoped orIReservationServicesingleton. Whether or notIReservationServicecan be singleton is only something you can find out.SsoSettingsProvideris only interested inLogonSettings, andLogonSettingsis a constant value that won't change after the application started, you should injectLogonSettingsdirectly inSsoSettingsProvider's constructor. This simplifiesSsoSettingsProviderand pushes loading theLogonSettingsto the Composition Root.