コード ライブラリ内のサービス プロバイダーのスコープと有効期間の規則を知っているコード ライブラリでサービスを提供するケースがいくつかあります。その情報をライブラリ自体で構成したいと考えていますが、その知識をコンポジション ルートにバブリングする必要はありません。
現在のバージョンの 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 は、、、およびクラスRegistry
で表されます。ライブラリのユーザーはテスト フィクスチャであり、メソッドはライブラリ ユーザーに記述してもらいたいコードを示します (オブジェクトを新規作成する代わりに、dll を含むパスを渡します)。Thing1
IThing1
Spike.SetUp()
Registry
Thing1
記述されたコードを使用すると、サービスを複数回フェッチするとSpike.GetThing1AndThing2()
、目的のシングルトン動作が示されます。Thing1
のように、公開されたインターフェイスを介してサービスを複数回フェッチしSpike.GetIThing1AndIThing2()
ても、シングルトンの動作は見られず、2 つの個別Thing1
のオブジェクトが構築されます。
それで、私が求めていることを行うことは可能ですか: コンポジションルートが形成されたときにスキャンを実行しながら、DLL 自体でシングルトンの動作を指定することはできますか?