2012-05-22 84 views
0

我們有幾種情況,我們在代碼庫中提供服務,我們知道代碼庫中服務提供者的範圍和生命週期規則。我們希望在圖書館本身配置這些信息,而不必讓知識冒泡到組合根目錄。我可以對Ninject中的對象進行分段配置嗎?

我一直無法弄清楚是否可以用當前版本的Ninject來實現這個功能。

using System; 
using System.Diagnostics.CodeAnalysis; 
using Ninject; 
using Ninject.Extensions.Conventions; 
using NUnit.Framework; 
using Ninject.Modules; 

[TestFixture] 
public class Spike 
{ 
    private IKernel kernel; 

    [SetUp] 
    public void SetUp() 
    { 
     this.kernel = new StandardKernel(); 

     this.kernel.Load(new Registry()); 

     this.kernel.Bind(x => x 
      .FromThisAssembly() 
      .SelectAllClasses() 
      .BindAllInterfaces() 
      ); 
    } 

    [TearDown] 
    public void TearDown() 
    { 
     Thing1.ResetCounts(); 
    } 

    [Test] 
    public void GetThing1AndThing2() 
    { 
     // arrange 
     var thing1 = this.kernel.Get<Thing1>(); 
     var thing2 = this.kernel.Get<Thing1>(); 

     // act 
     thing1.DoTheWork(); 
     thing2.DoTheWork(); 

     // assert 
     Assert.AreEqual(1, Thing1.ConstructorCount, "wrong number of constructor invocations"); 
     Assert.AreEqual(2, Thing1.DoTheWorkCount, "wrong number of method invocations"); 
    } 

    [Test] 
    public void GetIThing1AndIThing2() 
    { 
     // arrange 
     var thing1 = this.kernel.Get<IThing1>(); 
     var thing2 = this.kernel.Get<IThing1>(); 

     // act 
     thing1.DoTheWork(); 
     thing2.DoTheWork(); 

     // assert 
     Assert.AreEqual(1, Thing1.ConstructorCount, "wrong number of constructor invocations"); 
     Assert.AreEqual(2, Thing1.DoTheWorkCount, "wrong number of method invocations"); 
    } 

    public class Registry : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<Thing1>().ToSelf().InSingletonScope(); 
     } 
    } 

    public interface IThing1 
    { 
     void DoTheWork(); 
    } 

    public class Thing1 : IThing1 
    { 
     public static int ConstructorCount { get; set; } 
     public static int DoTheWorkCount { get; set; } 

     public Thing1() 
     { 
      Console.WriteLine("Thing1.ctor underway"); 
      ++Thing1.ConstructorCount; 
     } 

     public void DoTheWork() 
     { 
      Console.WriteLine("Thing1.DoTheWork underway"); 
      ++Thing1.DoTheWorkCount; 
     } 

     public static void ResetCounts() 
     { 
      Thing1.ConstructorCount = 0; 
      Thing1.DoTheWorkCount = 0; 
     } 
    } 
} 

在該試驗的情況下,ilbrary由RegistryThing1,和IThing1類表示。庫的用戶是測試夾具,其中Spike.SetUp()方法顯示我們理想地喜歡庫用戶編寫的代碼(它們將在包含dll的路徑中傳遞,而不是新建Registry對象)。

通過編寫的代碼,在Spike.GetThing1AndThing2()中多次獲取Thing1服務展示了所需的單例行爲。通過Spike.GetIThing1AndIThing2()中發佈的接口多次獲取Thing1服務不會顯示單身行爲,而是會構造兩個單獨的對象Thing1

所以有可能做我想問的問題:指定在DLL本身的單例行爲,同時在組合根形成時執行掃描?

回答

1

您需要引入約定。例如。添加指定範圍的屬性或使用命名約定,以便可以從名稱中識別範圍。

然後正確設置綁定約定。例如

this.kernel.Bind(x => x 
    .FromThisAssembly() 
    .SelectAllClasses() 
    .WithAttribute<SingletonAttribute>() 
    .BindAllInterfaces() 
    .Configure(binding => binding.InSingletonScope()); 

this.kernel.Bind(x => x 
    .FromThisAssembly() 
    .SelectAllClasses() 
    .WithAttribute<TransientAttribute>() 
    .BindAllInterfaces()); 
相關問題