У меня есть простое веб-приложение, использующее ASP.NET MVC3 и Ninject.Web.MVC (версия MVC3).
Все работает нормально, кроме случаев, когда приложение заканчивается. Всякий раз, когда это заканчивается, ядро удаляется, как видно из Application_End () в NinjectHttpApplication:
Отражатель говорит мне это:
public void Application_End()
{
lock (this)
{
if (kernel != null)
{
kernel.Dispose();
kernel = null;
}
this.OnApplicationStopped();
}
}
Что происходит, так это то, что мой веб-сервер выходит из строя со StackOverflowException (я пробовал и IIS7, и встроенный веб-сервер в VS2010). Я могу только предположить, что именно здесь все идет не так, потому что я сам не писал никакого кода в конце приложения.
Я понял, что ядро знает, как разрешить IKernel (который возвращает само ядро), может ли это быть причиной переполнения стека? Я мог предположить, что происходит нечто подобное:
- Kernel.Dispose ()
- Утилизировать все экземпляры в ядре
- эй! посмотрите на это, ядро тоже в ядре. Вернуться к шагу 1.
Другими словами, ядро удаляется, удаляет все содержащиеся в нем ссылки (включая самоотсылку), что приводит к его удалению.
Имеет ли это какой-то смысл?
Edit:
Кажется, проблема в NinjectHttpApplication. Посмотрите на этот код активации:
public void Application_Start()
{
lock (this)
{
kernel = this.CreateKernel();
...
kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();
...
}
}
Кажется, все в порядке, но сейчас происходит то, что всякий раз, когда вызывается IResolutionRoot, ядро кэшируется внутри себя. При утилизации ядра очищается кеш, который удаляет все кэшированные объекты, что вызывает циклическую ссылку.
Простым решением для NinjectHttpApplication было бы просто изменить привязку. Измените привязку константы на метод один:
kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();
становится
kernel.Bind<IResolutionRoot>().ToMethod(x => this.Kernel);
Это решает проблему, но я не уверен, является ли проблема кэширования всего циклического удаления ошибкой в ninject.