Замок Виндзор - Должен ли я выпускать однотонные или небезопасные переходные объекты?

Замок wiki говорит, что в нескольких местах я должен ВСЕГДА вызвать контейнер. Relelease() для компонентов, разрешенных через контейнер. Это, очевидно, имеет смысл для сложных методов управления жизненным стилем (например, LifeStyle.Pooled) или при использовании специализированных средств...

Но действительно ли мне нужно выпустить синглтон (который живет до размещения контейнера) и нереализованные переходные объекты?. Если я выхожу через вызовы Release() для переходных объектов или одиночных вызовов, эти вызовы кажутся быть лишним -.eg в случае переходных объектов, не реализующих IDisposable, ядро ​​просто замечает, что у него нет пути к объекту и возвращается...

Кажется, существует концепция "нагрузки компонента" для отслеживания "косвенных" ссылок на другие одноразовые компоненты, которые могут быть построены при разрешении переходного объекта. Я понимаю, что необходимо освободить временные объекты, если вы не знаете 100%, имеют ли они такие косвенные зависимости или нет. Является ли это основной причиной "побуждать" всех пользователей Castle к ALWAYS выпускать компоненты?

Ответ 1

Замок Wiki здесь немного строгий, пытаясь быть в безопасности, а не извиняться. Вероятно, он может использовать некоторые изменения.

В любом случае - вот как это работает.

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

Теперь, здесь часть, в которой играют жизни.

  • Singleton - по определению singleton являются "глобальными" в контексте контейнера - они создаются при первом запросе их и живут до конца жизненного цикла контейнера (что означает, что контейнер будет удален), Если вы видите документацию, на самом деле это говорит о том, что освобождение синглетов на самом деле ничего не делает. Это происходит только тогда, когда контейнер будет настроен на то, что вызовы, связанные с выводом из жизни ваших компонентов, будут вызваны.

  • Per (контекст: веб-запрос/сеанс WCF/) - поскольку объект совместно используется в четко определенном контексте с четким концом, конец контекста будет заботиться о выпуске ваших компонентов.

  • Transient - то, где могут возникать реальные проблемы. Поскольку переходные компоненты не имеют никакого конца в конце срока службы, и вы можете создавать кучи своих экземпляров в течение срока действия приложения, нет другого пути, кроме будучи явным и говорю контейнеру "эй, я больше не буду использовать этот объект, не стесняйтесь избавляться от него, спасибо за всех рыб".

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

Другое дело, что вы вызываете Resolve и Release. Вы должны только Release, что вы Resolve.

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

Итак, конечный результат: это не так страшно, как кажется.