Ninject的InSingletonScope()创建多个实例

时间:2016-09-22 08:14:30

标签: c# ninject

我们遇到的问题是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。

1 个答案:

答案 0 :(得分:0)

创建对象时,您具有循环依赖关系。

Ninject是尝试只创建一个Handler的实例,但它不能,因为在尝试实例化Handler时,它需要Part实例和创建Part的步骤是获取Handler的实例(Part的OnActiviation操作)。