Виндзорский контейнер: как заставить утилизировать объект?

У меня есть объект, который реализует IDisposable, который зарегистрирован в контейнере Windsor, и я хотел бы избавиться от него, чтобы вызывался метод Dispose, и при следующем вызове Resolve он выбирает новый экземпляр.

Имеет ли

container.Release(obj); 

автоматически вызвать Dispose () немедленно? Или мне нужно сделать

obj.Dispose();
container.Release(obj);

Не могу найти в документации ничего о том, что именно делает Release

РЕДАКТИРОВАТЬ: см. Мой ответ ниже для результатов испытаний, которые я провел. Теперь возникает вопрос: как заставить контейнер освободить экземпляр компонента с одноэлементным жизненным циклом? Это нужно сделать только в одном месте, и написание собственного жизненного цикла кажется слишком тяжелым, разве нет встроенного способа сделать это?

17.09.2008 16:44:14
3 ОТВЕТА
РЕШЕНИЕ

Я думаю, что это то, о чем люди на самом деле не знают при работе с контейнером Windsor - особенно часто удивительное поведение, когда одноразовые временные компоненты удерживаются контейнером в течение всего срока службы ядра до тех пор, пока он не утилизируется, если вы сами не освободите их - хотя это задокументировано - посмотрите здесь - но чтобы быстро процитировать:

MicroKernel имеет сменную политику выпуска, которая может подключаться и реализовывать некоторую маршрутизацию для утилизации компонентов. MicroKernel поставляется с тремя реализациями IReleasePolicy:

  • AllComponentsReleasePolicy: отслеживание всех компонентов для обеспечения правильного удаления при утилизации экземпляра MicroKernel
  • LifecycledComponentsReleasePolicy: отслеживать только компоненты, связанные с жизненным циклом вывода из эксплуатации
  • NoTrackingReleasePolicy: не отслеживает

Вы также можете реализовать собственную политику выпуска, используя интерфейс IReleasePolicy.

То, что вам может показаться более простым, - это изменить политику на NoTrackingReleasePolicy, а затем обработать утилизацию самостоятельно - это также потенциально рискованно, но если ваш образ жизни в основном временный (или если ваш контейнер утилизируется, ваше приложение все равно будет закрыто) это, вероятно, не имеет большого значения. Помните, однако, что любые компоненты, которые уже были введены синглтоном, будут содержать ссылку, так что вы можете в конечном итоге вызвать проблемы, пытаясь «обновить» свои синглтоны - это кажется плохой практикой, и мне интересно, возможно, вам удастся избежать необходимости Сделайте это в первую очередь, улучшив способ объединения ваших приложений.

Другие подходы состоят в том, чтобы создать собственный жизненный цикл с его собственной реализацией вывода из эксплуатации (поэтому выпуск синглтона фактически избавился бы от компонента, так же как и переходный жизненный цикл).

В качестве альтернативы другой подход заключается в том, чтобы декоратор для вашей службы был зарегистрирован в контейнере с одноэлементным образом жизни, но ваша фактическая базовая служба была зарегистрирована в контейнере с переходным образом жизни - тогда, когда вам нужно обновить компонент, просто избавьтесь от переходного базового компонента, который был сохранен. декоратором и замените его на недавно разрешенный экземпляр (разрешите его с помощью ключа компонентов, а не службы, чтобы избежать получения декоратора) - это позволяет избежать проблем с другими одноэлементными службами (которые не «обновляются») от удержания на устаревшие сервисы, которые были использованы для того, чтобы сделать их непригодными для использования, но для их работы требуется немного кастинга и т. д.

13
29.11.2018 13:56:45
У меня похожая проблема, мне очень нравится концепция декоратора. Хороший ...
Rohan West 9.11.2009 19:43:40
@Bittercoder, если я уничтожу контейнер, он вызовет dispose для одноэлементных объектов, как заставить его?
Brans Ds 7.09.2016 11:50:38

Это зависит от стиля жизни компонента, который вы указали при добавлении в контейнер.

Вы бы использовали Release (), если образ жизни объединен. Это помещает компонент обратно в пул для следующего извлечения (объект не уничтожен, поэтому удаление будет плохим)

если образ жизни временный, при получении компонента создается новый объект. В этом случае утилизация остается за вами, и вам не нужно звонить в Release

Если образ жизни - Поток, один и тот же компонент используется для каждого потока, а не уничтожается.

Если образ жизни синглтон, то создается только один компонент, а не разрушается.

Скорее всего, вы используете временные компоненты? (если вы беспокоитесь об их своевременной утилизации), в этом случае просто оберните его с использованием, и все готово (или вызовите утилизацию где-нибудь самостоятельно)

using(ISomeService service = container.Resolve<ISomeService>())
{
 // Do stuff here
 // service.Dispose is automatically called 
}

Редактировать - Да, чтобы «обновить» или утилизировать и воссоздать ваш синглтон, вам необходимо либо уничтожить контейнер, либо написать собственный жизненный цикл. Выполнение пользовательского жизненного цикла на самом деле не так сложно и сохраняет логику для этого в одном месте.

3
17.09.2008 18:53:07
На самом деле я делаю синглтоны, но хотел бы заставить его время от времени регенерировать компонент.
George Mauer 17.09.2008 17:30:19

Хорошо, так что я проводил тесты, и кажется, что Container.Release()неявно заставит Dispose()метод IDisposable запускаться только в том случае, если образ жизни временный (это, вероятно, не совсем правильно, но дело в том, что он не будет делать что-то чертовски, если образ жизни одиночный) ).

Теперь, если вы вызываете 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

К счастью, в моем случае я могу позволить себе просто отбросить все компоненты и довольно легко их восстановить. Однако это неоптимально.

1
27.10.2016 08:29:37