我们遇到了一个Ninject单例作用域类不止一次构建的问题。我将我们的代码缩减为一个展示奇怪行为的例子。 Handler是一个单元,它由一个具有复杂初始化的模块组成,由Handler构造函数执行。这就是使用ToMethod()进行模块绑定的原因。 Part也是一个单例,如果创建了Part,则创建Handler非常重要,这就是为什么我们在Part OnActivation回调中请求Handler。Ninject的InSingletonScope()创建多个实例
IKernel kernel = new StandardKernel();
kernel.Bind<Handler>().ToSelf().InSingletonScope();
kernel.Bind<Module>().ToMethod(x => x.Kernel.Get<Handler>().Module);
kernel.Bind<Part>().ToSelf().InSingletonScope().OnActivation(_ => kernel.Get<Handler>());
完整的代码,包括一些调试输出:
[Test]
public void NinjectShouldCreateOnlyOneHandler()
{
IKernel kernel = new StandardKernel();
kernel.Bind<Handler>().ToSelf().InSingletonScope();
kernel.Bind<Module>().ToMethod(x =>
{
Debug.WriteLine("Module ToMethod enter");
Module module = x.Kernel.Get<Handler>().Module;
Debug.WriteLine("Module ToMethod exit");
return module;
});
kernel.Bind<Part>().ToSelf().InSingletonScope().OnActivation(_ =>
{
Debug.WriteLine("Part OnActivation enter");
kernel.Get<Handler>();
Debug.WriteLine("Part OnActivation exit");
});
Debug.WriteLine("Get<Module>()");
kernel.Get<Module>();
Debug.WriteLine($"InstanceCount = {Handler.InstanceCount}");
Assert.AreEqual(1, Handler.InstanceCount);
}
public class Handler
{
public static int InstanceCount { get; private set; } = 0;
public Handler(Part part)
{
Debug.WriteLine($"Handler ctor, InstanceCount = {++InstanceCount}");
Module = new Module(part);
}
public Module Module { get; }
}
public class Module
{
public Module(Part part)
{
Debug.WriteLine("Module ctor");
}
}
public class Part
{
public Part()
{
Debug.WriteLine("Part ctor");
}
}
调试输出:
Get<Module>()
Module ToMethod enter
Part ctor
Part OnActivation enter
Handler ctor, InstanceCount = 1
Module ctor
Part OnActivation exit
Handler ctor, InstanceCount = 2
Module ctor
Module ToMethod exit
InstanceCount = 2
我想这个问题是,我们请求处理程序实例被创建同时,但因为它可以在那个时候构建 - 为什么不是那个实例用于下一个请求?
我期望Ninject宁愿抛出一个异常,而不是创建一个单例作用域类的两个实例。这是一个错误还是有我错过了什么?我们正在使用Ninject v3.2.2。
是的,但是在OnActivation回调中可以创建一个Handler *,我不明白为什么它不存储并返回到原始请求而不是创建另一个?另外,如果Ninject不能做我告诉它做的事情,我希望它会抛出一个异常,而不是创建一个标记为单例的类的多个实例。我想我需要把这个报告给Ninject开发者。 – Anlo