anonymous
anonymous

Reputation: 4064

IoC container and dll memory management

I'm working on a server project and the server has a few different, independent layers and a few singleton classes. And I use the SimpleInjector, an IoC container, all across the layers. The full, executable example source code is available at https://github.com/DamonJung/TestAdvanture001.. ( It's unnecessarily lengthy because I was trying to reproduce a different problem there. )

I access the Singleton from Main method directly and indirectly from the IoC container.

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

I expected the Singleton should be instantiated only once and the static instance should have the exact same memory address in the application, no matter where it's being invoked from and no matter how it's constructed ( by Main or the IoC container )

However, as the console output is saying, it didn't work that way. The Singleton's Instance shouldn't have been instantiated more than once. But they ended up having a different address on their own.

enter image description here

If my shallow understanding serves me right, the executable loads the dll into its own memory, and once the static member is created, the variable can be accessed throughout the AppDomain region.

Isn't this confirming the fact about static variables, isn't it?

Static Members

A non-static class can contain static methods, fields, properties, or events. The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created. Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.

I was in search for the relevant read in SimpleInjector's documentation and found none. Reading about dynamic linking library and its memory management doesn't come right at me ( I shall be reading it further and over and over again anyway ! )

Above items would be my ultimate questions.

Upvotes: 0

Views: 260

Answers (1)

Cyril Durand
Cyril Durand

Reputation: 16192

Two instances are created because your code creates two instances.

The first one is created by the following code

public class Singleton
{
    public static readonly Singleton Instance = new Singleton();
    // ....
}

and the second one is created when you register your type to SimpleInjector

If you want an instance to be created only once you could use a private constructor

public class Singleton
{
    static Singleton()
    {
        Singleton.Instance = new Singleton();
    }
    public static Singleton Instance { get; }

    private Singleton(){ 
    }
}

This way only the Singleton class create itself.

To register your singleton in SimpleInjector you can use the RegisterInstance method :

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

By the way it is more common to let the container manage instances by itself and not rely on static property which could indicate that you are using a service locator which is a common anti pattern.

If you want to let SimpleInjector manage the instance you should use

container.RegisterSingleton<Singleton>();

This way SimpleInjector will create only one Singleton instance for the container.

See Singleton lifestyle in the SimpleInjector documentation

Upvotes: 4

Related Questions