我们遇到的问题是Ninject单例范围类被多次构造。我已经将代码简化为一个展示奇怪行为的例子。 Handler是一个单例,由一个具有稍微复杂的初始化的模块组成,由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。
答案 0 :(得分:0)
创建对象时,您具有循环依赖关系。
Ninject是尝试只创建一个Handler
的实例,但它不能,因为在尝试实例化Handler
时,它需要Part
实例和创建Part
的步骤是获取Handler
的实例(Part
的OnActiviation操作)。