Самая последняя версия Ninject.Web.Mvc использует временную область для регистрации контроллеров в RegisterAllControllersIn
:
public void RegisterAllControllersIn(Assembly assembly,
Func<Type, string> namingConvention)
{
foreach (Type type in assembly.GetExportedTypes().Where(IsController))
_kernel.Bind<IController>()
.To(type)
.InTransientScope()
.Named(namingConvention(type));
}
Я тоже заглянул в класс NinjectControllerFactory
. Его функция CreateController довольно проста. Он делает TryGet в ядре для контроллера и возвращает то, что он возвращает - если он не может найти контроллер, он делегирует базовому классу:
public override IController CreateController(RequestContext requestContext,
string controllerName)
{
var controller = Kernel.TryGet<IController>(controllerName.ToLowerInvariant());
if (controller == null)
return base.CreateController(requestContext, controllerName);
var standardController = controller as Controller;
if (standardController != null)
standardController.ActionInvoker = new NinjectActionInvoker(Kernel);
return controller;
}
Итак, исходя из настроек привязки и фабрики, может показаться, что это не создание объектов в области действия Singleton. Одна вещь, которую вы могли бы сделать, это написать небольшой отладочный код после того, как вы создадите свое ядро и сами проверите привязки, чтобы подтвердить область действия. Я провел небольшой эксперимент и добавил код в мое шоу класса HttpApplication ниже. Полное раскрытие, это использование ASP.Net MVC 1.0, поэтому ваш пробег может отличаться. Если у меня будет возможность, я получу последний предварительный просмотр MVC 2. и попробую тот же эксперимент.
protected void DumpBindings() {
var bindings = Kernel.GetBindings(typeof(IController));
var dummyRequest = new RequestContext(
new HttpContextWrapper(HttpContext.Current),
new RouteData());
foreach (var binding in bindings) {
var scope = "Custom";
if (binding.ScopeCallback == StandardScopeCallbacks.Request)
scope = "Request";
else if (binding.ScopeCallback == StandardScopeCallbacks.Singleton)
scope = "Singleton";
else if (binding.ScopeCallback == StandardScopeCallbacks.Thread)
scope = "Thread";
else if (binding.ScopeCallback == StandardScopeCallbacks.Transient)
scope = "Transient";
HttpContext.Current.Trace.Write(
string.Format(
"Controller: {0} Named: {1} Scope: {2}",
binding.Service.Name,
binding.Metadata.Name,
scope));
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
var controller1 = controllerFactory.CreateController(
dummyRequest, binding.Metadata.Name);
var controller2 = controllerFactory.CreateController(
dummyRequest, binding.Metadata.Name);
HttpContext.Current.Trace.Write(
string.Format(
"{0} controller1 == {0} controller2 ? {1}",
binding.Metadata.Name,
object.Equals(controller1, controller2)));
}
}
Я позвонил сразу после звонка на RegisterAllControllersIn
в OnApplicationStarted
. В результате вывода трассировки были созданы следующие сообщения:
Контроллер: Имя IController: home
Область применения: Переходный домашний контроллер1
== домашний контроллер2? Ложный контроллер: IController Named: account
Область применения: временный контроллер аккаунта 1
== контроллер аккаунта2? Неверно
Итак, все, что это делает, это подтверждает, что используется переходная область и что фабрика контроллеров возвращает другой экземпляр того же контроллера по запросу. Итак, единственное, о чем я могу думать, это то, что:
- Возможно, вы не используете последние сборки Ninject 2 и Ninject.Web.Mvc
- Проблема на уровне MVC - то есть повторное использование контроллера, созданного на заводе