Виндзорский контейнер:Как принудительно избавиться от объекта?
-
01-07-2019 - |
Вопрос
У меня есть объект, который реализует IDisposable, зарегистрированный в контейнере Windsor, и я хотел бы избавиться от него, чтобы вызывался его метод Dispose, и при следующем вызове Resolve он извлекал новый экземпляр.
Делает
container.Release(obj);
автоматически вызывать Dispose() немедленно?Или мне нужно что-то сделать
obj.Dispose();
container.Release(obj);
Не удалось найти ничего в документации о том, что именно делает Release
Редактировать: Смотрите мой ответ ниже с результатами тестов, которые я провел.Теперь возникает вопрос, как мне заставить контейнер выпустить экземпляр компонента с одноэлементным жизненным циклом?Это нужно сделать только в одном месте, и написание пользовательского жизненного цикла кажется слишком тяжеловесным, неужели нет встроенного способа сделать это?
Решение
Это то, о чем, я думаю, люди на самом деле не осознают при работе с контейнером Windsor, особенно часто удивительно поведение, при котором одноразовые переходные компоненты сохраняются контейнером в течение всего срока службы ядра до тех пор, пока оно не будет удалено, если вы не освободите их самостоятельно - хотя это задокументировано - взгляните здесь - но чтобы быстро процитировать:
Микроядро имеет подключаемую политику выпуска, которая может подключать и реализовывать некоторую маршрутизацию для удаления компонентов.Микроядро поставляется с тремя реализациями IReleasePolicy:
- Allcomponentsрелиз политики:отслеживайте все компоненты, чтобы обеспечить правильное удаление при удалении экземпляра микроядра
- Lifecycledcomponentsрелиз политики:отслеживайте только компоненты, с которыми связан жизненный цикл вывода из эксплуатации
- Не отслеживатьрелизную политику:не выполняет никакого отслеживания
Вы также можете реализовать свою собственную политику выпуска, используя интерфейс IReleasePolicy.
Что вам, возможно, покажется проще, так это изменить политику на Не отслеживатьрелизную политику а затем обработайте утилизацию самостоятельно - это тоже потенциально рискованно, но если ваш образ жизни в значительной степени преходящ (или если при утилизации вашего контейнера ваше приложение все равно вот-вот закроется), это, вероятно, не имеет большого значения.Помните, однако, что любые компоненты, которые уже были введены с помощью singleton, будут содержать ссылку, поэтому у вас могут возникнуть проблемы при попытке "обновить" ваши синглтоны - это кажется плохой практикой, и я задаюсь вопросом, возможно, вы сможете избежать необходимости делать это в первую очередь, улучшив способ объединения ваших приложений.
Другие подходы заключаются в создании пользовательского жизненного цикла с его собственной реализацией вывода из эксплуатации (таким образом, выпуск синглтона фактически приведет к удалению компонента, подобно переходному жизненному циклу).
В качестве альтернативы, другой подход заключается в том, чтобы иметь декоратор для вашей службы, зарегистрированный в контейнере с одноэлементным стилем жизни, но ваша фактическая базовая служба зарегистрирована в контейнере с временным стилем жизни - тогда, когда вам нужно обновить компонент, просто удалите временный базовый компонент, удерживаемый декоратором, и замените его свежим разрешенным экземпляром (разрешите его, используя ключ components, а не service, чтобы избежать получения декоратора) - это позволяет избежать проблем с другими одноэлементными сервисами (которые не "обновляются") из-за использования устаревших сервисов, которые были удалены, что делает их непригодными для использования, но требует небольшого приведения и т. Д .чтобы заставить это сработать.
Другие советы
Это зависит от образа жизни компонента, который вы указали, когда добавляли его в контейнер.
Вы бы использовали Release(), если образ жизни объединен.Это помещает компонент обратно в пул для следующего извлечения (объект не уничтожается, поэтому утилизация была бы плохой).
если образ жизни является временным, при получении компонента создается новый объект.В этом случае утилизация зависит от вас, и вам не нужно вызывать Release
Если стилем жизни является поток, то для каждого потока используется один и тот же компонент, а не уничтожается.
Если стиль жизни одноэлементный, создается только один компонент, а не уничтожается.
Скорее всего, вы используете переходные компоненты?(если вы обеспокоены их своевременной утилизацией) в этом случае просто оберните это с помощью using, и все готово (или вызовите dispose самостоятельно где-нибудь)
using(ISomeService service = container.Resolve<ISomeService>())
{
// Do stuff here
// service.Dispose is automatically called
}
Редактировать - Да, для того, чтобы "обновить" или утилизировать и воссоздать ваш синглтон, вам нужно будет либо уничтожить контейнер, либо написать пользовательский жизненный цикл.Выполнение пользовательского жизненного цикла на самом деле не так сложно, и логика для этого сохраняется в одном месте.
Хорошо, итак, я провел тесты, и, похоже, Container.Release()
БУДЕТ неявно вызывать IDisposable Dispose()
метод выполняется только в том случае, если образ жизни является временным (это, вероятно, не совсем корректно, но суть в том, что он ничего не сделает, если образ жизни одноэлементный).
Теперь, если ты позвонишь Container.Dispose()
он также вызовет одноразовые методы, хотя, к сожалению, он удалит все ядро целиком, и вам придется добавить все компоненты обратно в:
var container = new WindsorContainer();
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj = container.Resolve<MyDisposable>(); // Create a new instance of MyDisposable
obj.DoSomething();
var obj2 = container.Resolve<MyDisposable>(); // Returns the same instance as obj
obj2.DoSomething();
container.Dispose(); // Will call the Disposable method of obj
// Now the components need to be added back in
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj3 = container.Resolve<MyDisposable>(); // Create a new instance of MyDisposable
К счастью, в моем случае я могу позволить себе просто удалить все компоненты и восстановить их довольно легко.Однако это неоптимально.