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

StackOverflow https://stackoverflow.com/questions/85183

Вопрос

У меня есть объект, который реализует 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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top