Виндзорский контейнер: как заставить утилизировать объект? - PullRequest
11 голосов
/ 17 сентября 2008

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

ли

container.Release(obj); 

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

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

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

EDIT: Смотрите мой ответ ниже для результатов испытаний, которые я провел. Теперь возникает вопрос, как заставить контейнер освободить экземпляр компонента с одноэлементным жизненным циклом? Это нужно сделать только в одном месте, и написание собственного жизненного цикла кажется слишком тяжелым, разве нет встроенного способа сделать это?

Ответы [ 3 ]

12 голосов
/ 03 октября 2008

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

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

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

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

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

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

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

3 голосов
/ 17 сентября 2008

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

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

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

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

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

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

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

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

1 голос
/ 17 сентября 2008

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

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

...