代码之家  ›  专栏  ›  技术社区  ›  hina10531

IoC容器和dll内存管理

  •  0
  • hina10531  · 技术社区  · 6 年前

    我正在处理一个服务器项目,服务器有几个不同的、独立的层和几个单例类。我使用 SimpleInjector https://github.com/DamonJung/TestAdvanture001 .. ( 这是不必要的冗长,因为我试图重现一个不同的问题。 )

    我访问 Singleton Main 方法直接或间接地从IoC容器获取。

    // 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();
        .
        .
    }
    

    单子 应该只实例化一次,并且静态实例在应用程序中应该具有完全相同的内存地址,无论从何处调用它,也不管它是如何构造的(通过 主要 或IoC容器)

    然而,正如控制台输出所说,它并不是这样工作的。这个 Instance 不应该被实例化多次。但最后他们自己有了不同的地址。

    enter image description here

    如果我的浅显理解是正确的,那么可执行文件会将dll加载到自己的内存中,一旦创建了静态成员,就可以在整个过程中访问该变量 AppDomain

    不是吗 this 证实了关于静态变量的事实,不是吗?

    静态成员

    无论创建了多少个类实例,静态成员只存在一个副本 . 静态方法和属性不能访问其包含类型中的非静态字段和事件,也不能访问任何对象的实例变量,除非它显式地在方法参数中传递。

    SimpleInjector's 没有找到任何文档。关于动态链接库和它的内存管理的阅读对我来说并不合适(无论如何,我还是会一次又一次地读下去!)

    • 程序如何在内存管理方面处理DLL
    • 简单喷射器 当依赖项通过 Container.Register();

    以上是我的终极问题。

    0 回复  |  直到 6 年前
        1
  •  4
  •   Cyril Durand    6 年前

    创建两个实例是因为代码创建了两个实例。

    第一个由以下代码创建

    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 类创建自己。

    RegisterInstance 方法:

    container.RegisterInstance<Singleton>(Singleton.Instance);
    

    顺便说一句,更常见的做法是让容器自己管理实例,而不依赖于静态属性,这可能表示您正在使用 service locator 这是常见的反模式。

    如果你想让 管理您应该使用的实例

    container.RegisterSingleton<Singleton>();
    

    这种方式 简单喷射器 将只创建一个 容器的实例。

    看到了吗 Singleton lifestyle in the SimpleInjector documentation