2016-09-22 106 views
2

我们遇到了一个N​​inject单例作用域类不止一次构建的问题。我将我们的代码缩减为一个展示奇怪行为的例子。 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。

回答

0

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

Ninject是试图创造Handler只有一个实例,但不能因为试图实例Handler的时候,它需要一个Part实例,并在创建Part一个步骤是让为Handler(在OnActiviation动作实例Part)。

+0

是的,但是在OnActivation回调中可以创建一个Handler *,我不明白为什么它不存储并返回到原始请求而不是创建另一个?另外,如果Ninject不能做我告诉它做的事情,我希望它会抛出一个异常,而不是创建一个标记为单例的类的多个实例。我想我需要把这个报告给Ninject开发者。 – Anlo