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

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

Делает

container.Release(obj); 

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

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

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

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


person George Mauer    schedule 17.09.2008    source источник


Ответы (3)


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

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

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

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

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

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

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

person Bittercoder    schedule 03.10.2008
comment
У меня похожая проблема, мне очень нравится концепция декоратора. Хороший... - person Rohan West; 09.11.2009
comment
@Bittercoder, если я удаляю контейнер, будет ли он вызывать dispose для одноэлементных объектов, как заставить его? - person Brans Ds; 07.09.2016

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

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

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

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

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

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

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

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

person Philip Rieck    schedule 17.09.2008
comment
На самом деле я делаю синглтоны, но иногда хотел бы заставить его регенерировать компонент. - person George Mauer; 17.09.2008

Хорошо, я проводил тесты, и кажется, что 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

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

person George Mauer    schedule 17.09.2008