Ninject InSingletonScope 创建多个实例
Ninject InSingletonScope Creating multiple instances
我有一个非常简单的测试项目,我尝试告诉 ninject 我的 ILoader 实例应该是单例。无论我做什么,它都会创建它的多个实例。
简单的界面。
public interface ILoader
{
IEnumerable<int> Get();
}
为测试目的实施
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public void Set(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
Class那要看
public class TestClass
{
private ILoader _loader;
public TestClass(ILoader loader)
{
_loader = loader;
}
public void Init()
{
foreach (var i in _loader.Get())
Console.WriteLine(i);
}
}
模块
public class TestModule : NinjectModule
{
public override void Load()
{
Bind<ILoader>().To<TestLoader>();
Bind<TestLoader>().ToSelf().InSingletonScope();
}
}
和运行它。
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new TestModule());
var ds = new List<int> { 1, 2 };
kernel.Get<TestLoader>().Set(ds);
var tc = kernel.Get<TestClass>();
tc.Init();
Console.ReadLine();
}
}
这里我想用测试数据预加载我的加载器,ninject 应该将完全相同的加载器注入我的测试Class。然而,它创建了一个新实例,这并不是真正想要的行为。
我想有办法解决这个问题。但是 InSingletonScope 的目的是什么?我不应该告诉 ninject 我想要一个而且只有一个 ILoader 实例吗?
您应该像这样使用构造函数注入(参见 )而不是 Set
方法:
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public TestLoader(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
下面是注册和解析它的方法:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope()
.WithConstructorArgument("enumerable", ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}
在此示例中,TestClass
的两个实例将获得相同的 TestLoader
实例注入其中。
如果出于某种原因你不想使用构造函数注入并且你想保留 Set
方法,你可以这样做:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope();
((TestLoader)kernel.Get<ILoader>()).Set(ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}
我有一个非常简单的测试项目,我尝试告诉 ninject 我的 ILoader 实例应该是单例。无论我做什么,它都会创建它的多个实例。
简单的界面。
public interface ILoader
{
IEnumerable<int> Get();
}
为测试目的实施
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public void Set(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
Class那要看
public class TestClass
{
private ILoader _loader;
public TestClass(ILoader loader)
{
_loader = loader;
}
public void Init()
{
foreach (var i in _loader.Get())
Console.WriteLine(i);
}
}
模块
public class TestModule : NinjectModule
{
public override void Load()
{
Bind<ILoader>().To<TestLoader>();
Bind<TestLoader>().ToSelf().InSingletonScope();
}
}
和运行它。
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new TestModule());
var ds = new List<int> { 1, 2 };
kernel.Get<TestLoader>().Set(ds);
var tc = kernel.Get<TestClass>();
tc.Init();
Console.ReadLine();
}
}
这里我想用测试数据预加载我的加载器,ninject 应该将完全相同的加载器注入我的测试Class。然而,它创建了一个新实例,这并不是真正想要的行为。
我想有办法解决这个问题。但是 InSingletonScope 的目的是什么?我不应该告诉 ninject 我想要一个而且只有一个 ILoader 实例吗?
您应该像这样使用构造函数注入(参见 Set
方法:
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public TestLoader(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
下面是注册和解析它的方法:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope()
.WithConstructorArgument("enumerable", ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}
在此示例中,TestClass
的两个实例将获得相同的 TestLoader
实例注入其中。
如果出于某种原因你不想使用构造函数注入并且你想保留 Set
方法,你可以这样做:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope();
((TestLoader)kernel.Get<ILoader>()).Set(ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}