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;
}
したがって、バインディングの設定とファクトリに基づくと、シングルトンスコープでオブジェクトを作成していないように見えます。カーネルを作成した後、小さなデバッグコードを記述し、バインディングを自分でチェックして、スコープが何であるかを確認することができます。少し実験をして、以下の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?False Controller:IController Named:account
Scope:Transient account controller1
== account controller2?誤り
したがって、これはすべて、一時スコープが使用されていること、およびコントローラーファクトリが要求されたときに同じコントローラーの別のインスタンスを返していることを確認することです。だから、私が考えることができる唯一のことはそれです:
- おそらく、Ninject2とNinject.Web.Mvcの最新ビルドを使用していません
- 問題はMVCレベルにあります。つまり、工場で作成されたコントローラーを再利用しています。