2016-03-16 37 views
1

我正在創建一個Web API,我正在使用依賴注入機智Ninject。Ninject是否創建2個獨立的上下文?

我:

IRTWRepository IModelFactory

我注射那些2到我的控制器這樣。

private static void RegisterServices(IKernel kernel) 
     { 
      kernel.Bind<IRTWRepository>().To<RTWRepository>(); 
      kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();   
      kernel.Bind<IModelFactory>().To<ModelFactory>(); 
     } 

我RTWRepository構造看起來像這樣

public class RTWRepository :IRTWRepository 
    { 
     private RTWAPIContext _context; 

     public RTWRepository(RTWAPIContext context) 
     { 
      _context = context; 
     }} 

我ModelFactory構造看起來像這樣

public class ModelFactory : IModelFactory 
    { 
     private IRTWRepository _repo;   

     public ModelFactory(IRTWRepository repo) 
     { 
      _repo = repo; 
     } 
} 

我有一個控制器,看起來像這樣:

public MaterialsController(IRTWRepository repository,IModelFactory modelFactory) 
      : base(repository,modelFactory) 
     { 

     } 

現在,我的追求離子是:Ninject是否在創建RTWRepository的實例時以及創建ModelFactory的實例時創建2個獨立的上下文?

我這樣問的原因是因爲當我試圖保存一個具有依賴關係的實體時,它遇到了一個問題,而該另一個對象以前是從db中檢索的。

我將實體保存在我的控制器中,但是我在模型工廠中創建它並伴隨依賴項。

public class RecycleCenter 
    { 
     public RecycleCenter() 
     { 

     } 

     public int MyProperty { get; set; } 


     [Required] 
     public virtual Address Address { get; set; }   
    } 

上面的代碼是針對實體回收中心,該中心有一個地址,這個回收中心實體在我的模型工廠創建,然後在我的控制器我試圖挽救它,但是當我的倉庫執行此行

_context.RecycleCenters.Add(entity); 

我得到這個錯誤

An entity object cannot be referenced by multiple instances of IEntityChangeTracker 

因此,地方在我的代碼我使用2環境,而不是1,我想創建時3210和RTWRepository,這個假設是否正確?如果是的話,我該如何解決?

回答

1

TL; DR;

你可能需要改變這一行:

kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();  

kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestContext();  

說明:

當你定義一個在Ninject綁定,還可以指定該對象的生命週期應該如何處理。

如果您沒有明確定義它,Ninject的默認生命週期是TransientTransient意味着每次需要實例時,它都會創建一個新實例。在你的情況下,你需要兩個實例:一個用於ModelFactoryRTWRepository,另一個用於MaterialsControllerRTWRepository

您可以修改的生活方式,其中一個選項:

  • 辛格爾頓==>kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InSingleTonScope();
  • 請求==>kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestScope();
  • 主題==>kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InThreadScope();
  • 命名,電話,家長,自定義

對您而言,我認爲您需要InRequestScope,但您必須檢查必要的生命週期,因爲它取決於應用程序。

欲瞭解更多信息,請點擊這裏檢查出的文檔:https://github.com/ninject/ninject/wiki/Object-Scopes

1

很可能是這樣。沒有任何註釋告訴Ninject「嘿,停下來,當你創建實例一次,重新使用它」。你應該同意,在大多數情況下,你會想要一個對象的多個實例,並且這是一種罕見的情況,只需要一次。

如果要重新使用該實例,請使用單例模式。 Ninject是熟悉它,這樣你就可以在對象映射結合的方法

kernel.Bind<RTWAPIContext>().ToMethod(c => RTWAPIContext.GetInstance()); 

還有一個ToSingleton約束力,但我敢打賭,你不能讓你的上下文構造私人和實施C#具體單身由於其他ASP。 NET問題(例如,ASP.NET Identity將嘗試調用上下文的方法來創建對象)。

+1

的'ToSingleton'法無關與類的實現。你可以定義一個普通的類,Ninject只會創建一個實例,然後重用它。不需要私人構造函數。 – Kenneth

+0

感謝您的評論。我不知道。其實我的評論是關於ASP.NET Identity在默認情況下在ApplicationDbContext中創建的'Create()'方法。所以我的想法是,如果一個人真的只想要一個實例,將該方法更改爲單身人士 - 由Ninject使用,由開發人員和身份 –