我们有几个案例,我们在代码库中提供服务,我们知道代码库中服务提供者的范围和生命周期规则。我们希望在库本身中配置该信息,而不必将该知识冒泡到组合根。
我一直无法弄清楚是否可以使用当前版本的 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;
}
}
}
在这个测试用例中,图书馆由Registry
、Thing1
和IThing1
类表示。库的用户是测试夹具,该Spike.SetUp()
方法显示了我们希望库用户编写的理想代码(他们将传递包含 dll 的路径而不是新建Registry
对象)。
使用编写的代码,Thing1
多次获取服务会Spike.GetThing1AndThing2()
表现出所需的单例行为。Thing1
通过其发布的接口多次获取服务Spike.GetIThing1AndIThing2()
不会表现出单例行为,而是构造两个单独的Thing1
对象。
那么是否可以按照我的要求做:在 DLL 本身中指定单例行为,同时在形成组合根时执行扫描?