【发布时间】:2017-01-30 17:10:47
【问题描述】:
我们遇到了不止一次构造 Ninject 单例作用域类的问题。我已经将我们的代码简化为一个展示奇怪行为的示例。 Handler 是一个单例,它由一个具有复杂初始化的 Module 组成,由 Handler 构造函数执行。这就是使用 ToMethod() 进行模块绑定的原因。 Part也是一个单例,如果创建了Part,则创建Handler非常重要,这就是我们在Part OnActivation回调中请求Handler的原因。
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
我想问题是我们在创建 Handler 实例时请求它,但既然它可以在那时构造 - 为什么不将该实例用于下一个请求?
我希望 Ninject 宁愿抛出异常而不是创建单例作用域类的两个实例。这是一个错误还是我错过了什么?我们正在使用 Ninject v3.2.2。
【问题讨论】: