Замок Windsor PerWebRequest объект вводится в объект Singleton без ссылки на него в поле
Мы создали одноэлементный объект (SsoSettingsProvider), в который вводим объект с образом жизни PerWebRequest (IReservationService в нашем примере это клиент WCF). В конструкторе мы используем этот объект для получения некоторых данных и помещаем эти данные в приватное поле.
public class SsoSettingsProvider : ISsoSettingsProvider
{
readonly LogonSettings _logonSettings;
public SsoSettingsProvider(IReservationService reservationService)
{
_logonSettings = reservationService.GetSSOSettings();
}
}
Если мы посмотрим на возможные несоответствия образа жизни в Виндзорском замке, то будет сказано:
"Компонент SsoSettingsProvider / ISsoSettingsProvider" с образом жизни Singleton зависит от "позднего связывания IReservationService" с образом жизни PerWebRequest. Этот тип зависимости обычно нежелателен и может привести к различным ошибкам ".
Эта информация говорит о том, что есть только возможность, но в этом случае я думаю, что это не проблема, потому что на внедренный объект нет ссылки в поле, поэтому он может быть собран мусором. я прав?
1 ответ
в этом случае я думаю, что это не проблема, потому что на внедренный объект нет ссылки в поле, поэтому он может быть собран мусором. я прав?
Замок Виндзор предупреждает о пленнических зависимостях. Основная проблема не столько в том, что экземпляры не являются сборщиком мусора, но в классе будет повторно использоваться экземпляр, который не предназначен для повторного использования.
Простой пример, когда вы вводите DbContext
в класс, который настроен как синглтон. Хотя это приведет к DbContext
поддерживается до тех пор, пока его единый потребитель не выйдет из области видимости (что обычно происходит, когда заканчивается приложение). DbContext
однако не следует повторно использовать несколько запросов. Во-первых, потому что это просто не потокобезопасно. Кроме того, он очень скоро устареет, что заставляет его возвращать кэшированные данные вместо повторного запроса к базе данных.
По этой причине мы регистрируем DbContext обычно как Scoped. Это, однако, означает, что все его потребители должны жить не более DbContext
, чтобы предотвратить его нарушение приложения. Это то, о чем Касл предупреждает.
В вашем случае, однако, вы не храните IReservationService
в частном поле SsoSettingsProvider
, Это все еще будет проблемой, потому что было бы разумно ожидать, что объекты, которые IReservationService
возврат не переживает IReservationService
(иначе IReservationService
будет зарегистрирован как синглтон). Так как с точки зрения SsoSettingsProvider
нет никакого способа узнать, безопасно ли хранить LogonSettings
Гораздо лучше не хранить его вообще.
Кроме того, как выражено здесь, конструкторы инъекций не должны вообще использовать свои зависимости. Это приводит к медленному и ненадежному составу объекта.
Поэтому, даже если вы проанализировали свой дизайн и точно знаете, что это работает в вашем конкретном случае, я бы посоветовал вам сделать одно из следующих действий:
- хранить
IReservationService
как частное поле вSsoSettingsProvider
и позвонитьGetSSOSettings
только когда один изSsoSettingsProvider
зовут и мешают запоминатьLogonSettings
, Это заставляет вас сделать либоSsoSettingsProvider
ограничен илиIReservationService
синглтон. Так или иначеIReservationService
Может быть синглтон это только то, что вы можете узнать. - В случае
SsoSettingsProvider
заинтересован только вLogonSettings
, а такжеLogonSettings
это постоянное значение, которое не изменится после запуска приложения, вы должны ввестиLogonSettings
прямо вSsoSettingsProvider
конструктор. Это упрощаетSsoSettingsProvider
и толкает загрузкуLogonSettings
в корень композиции.