2013-10-14 3 views
3

Мой конкретный контекст - это самодостаточное приложение Nancy, в котором я использую встроенную базу данных документов RavenDb.NancyFx - Как удалить экземпляры, зарегистрированные как singleton в контейнере приложений?

Мой самозагрузки выглядит следующим образом:

public class MyBootstrapper : DefaultNancyBootstrapper 
{ 
    protected override void ConfigureApplicationContainer(TinyIoCContainer container) 
    { 
     base.ConfigureApplicationContainer(container); 

     container.Register<IDocumentStore>(CreateDefaultStore()); 
     container.Register<IDoSomething, MyOtherType>().AsSingleton(); // implements IDisposable 
    } 

    private static IDocumentStore CreateDefaultStore(){...} 
} 

Проблема заключается в том, что я ожидал, что Dispose метод IDocumentStore и моего пользовательского одноразового типа, который будет вызываться, когда NanyHost остановлен.

NancyHost реализует IDisposable, TinyIoCContainer реализует IDisposable, если я зарегистрирую тип, который реализует IDisposable в контейнер запроса, он будет удален. Я был почти уверен, что при размещении Хоста контейнер будет удален и все зарегистрированные экземпляры будут удалены.

Я знаю, что я могу хранить ссылку на хранилище документов вне загрузчика и утилизировать его после того, как хозяин останавливается, и я могу думать о некоторых других уловках, как имеющий bootstraper реализовать IDisposable и утилизировать его вручную после того, как хозяин но я был уверен, что существует более автоматический способ обработки всех зарегистрированных случаев.

Я пропустил какой-то умный способ вызова Dispose() для экземпляров singleton, зарегистрированных в контейнере приложения?

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

UPDATE: После отправки сообщения, i'I've нашел this thread on the nancy group, который имеет некоторую информацию, связанную с этим, но староват.

+0

Singleton созданы для того, чтобы жить до тех пор, пока не прекратятся приложения, так почему вы хотите избавиться от чего-то, что невозможно? – VeNoMiS

+0

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

+0

@IulianMargarintescu - вы никогда не ставили неуправляемые ресурсы в статическом экземпляре, чтобы начать с ... Хранилище документов не является неуправляемым ресурсом. Если его не утилизировать должным образом, это не имеет значения. – Phill

ответ

2

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

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

https://github.com/NancyFx/Nancy/pull/1268

+0

Спасибо. Перезапуск хоста в сценарии, запущенном в slef, может упростить одну из моих учетных записей. –

2

Чтение источника, который вы предоставляете, RavenDb полностью не реализует шаблон IDIsposable. Согласно наилучшей практике, a class which implements IDisposable should have finalizer, which cleans unmanaged resources. В этом случае GC будет делать все, что требуется.

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

Если у вас есть проблемы, вы можете:

  1. файл запрос ошибки против RavenDb, поэтому они устанавливают, что
  2. Используйте обертку DocumentStore, который реализует IDisposable шаблона правильно.

В любом случае, я не вижу, чтобы «ретрансляция на .Net-каркасе, чтобы выполнять свою работу», была плохим, если не существует доказанной ошибки/необходимости. Поскольку предполагается, что контейнер приложения существует на протяжении всего жизненного цикла приложения, когда приложение прекращается, GC позаботится о правильном размещении.

+0

всякий раз, когда я вижу что-то реализующее IDisposable, особенно для стороннего кода, я чувствую, что должен его уничтожить. Это было бы правильно, если экземпляр живет до конца приложения, но также будет оставаться верным, если предположение изменится в будущем, а экземпляр имеет более короткий срок службы. Таким образом, хотя на данный момент это не проблема, так как GC будет выполнять свою работу, если мне это ничего не стоит, я скорее буду будущим доказательством и располагаю экземпляром. Также с изменением Стивена Роббинса мне не нужно ничего менять в своем коде, и поведение было бы тем, чего я ожидал в первую очередь. –

+0

Я согласен, что когда вы видите IDisposable, вам нужно его использовать. Он предназначался для этого - распоряжаться ресурсом, как только он вам больше не нужен. В области приложения - это ... после завершения приложения :). В любом случае, изменение, которое делает Стивен Роббинс, хорошо подходит для конкретной ситуации. –

Смежные вопросы