我正在处理一个服务器项目,该服务器具有一些不同的独立层和一些单例类。我使用SimpleInjector
(一个IoC容器)跨所有层。完整的可执行示例源代码可从https://github.com/DamonJung/TestAdvanture001获得。(不必要冗长,因为我试图在那里重现另一个问题。)
我直接从IoC容器间接访问Singleton
中的Main
方法。
// Use case in Main
.
.
using Impl;
static void Main(string args[])
{
.
.
// Singleton.Instance address = 0x0301f001 for example.
var context = Singleton.Instance.GetContext();
// SimpleInjector
// Singleton.Instance address inside of the dependency = 0x0408f023 for example.
var di = Container.GetInstance<ISomeInterface>();
var contextFromIoC = di.GetContext();
.
.
}
我希望Singleton
仅应实例化一次,并且静态实例在应用程序中应该具有完全相同的内存地址,无论从何处调用它,以及如何构造(由{{1} }或IoC容器
但是,正如控制台输出所表明的那样,它不是那样工作的。 Main
的{{1}}不应被多次实例化。但是他们最终自己有了一个不同的地址。
如果我的浅见正确,可执行文件会将dll加载到其自己的内存中,一旦创建了静态成员,就可以在整个Singleton
区域中访问该变量。
不是this确认有关静态变量的事实,不是吗?
静态成员
非静态类可以包含静态方法,字段,属性或事件。即使没有创建该类的实例,该静态成员也可以在该类上调用。始终通过类名称而不是实例名称访问静态成员。 仅存在一个静态成员的副本,无论创建了多少个该类实例。静态方法和属性无法访问其包含类型的非静态字段和事件,除非在方法参数中明确传递了实例变量,否则它们无法访问任何对象的实例变量。
我在搜索Instance
文档中的相关内容,但没有找到。对动态链接库及其内存管理的了解并不适合我(反正我会一遍又一遍地阅读它!)
AppDomain
在通过SimpleInjector's
注册依赖项时如何处理依赖项以上是我的最终问题。
答案 0 :(得分:1)
因为您的代码创建了两个实例,所以创建了两个实例。
第一个是由以下代码创建的
public class Singleton
{
public static readonly Singleton Instance = new Singleton();
// ....
}
,当您将类型注册到SimpleInjector
如果只想创建一次实例,则可以使用私有构造函数
public class Singleton
{
static Singleton()
{
Singleton.Instance = new Singleton();
}
public static Singleton Instance { get; }
private Singleton(){
}
}
这样,只有Singleton
类会自行创建。
要在SimpleInjector中注册单身人士,可以使用RegisterInstance
方法:
container.RegisterInstance<Singleton>(Singleton.Instance);
通过这种方式,更常见的是让容器自己管理实例而不依赖于静态属性,这可能表明您使用的是service locator,这是一种常见的反模式。
如果您想让SimpleInjector
管理您应该使用的实例
container.RegisterSingleton<Singleton>();
通过这种方式SimpleInjector
只会为容器创建一个Singleton
实例。