2016-09-22 111 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