ASP.NET Core Replacing a Singleton Instance at Runtime

Viewed 6747

I need to keep an object in memory for the lifetime of the ASP.NET Core application in which I serialize this object and store it in durable storage as a snapshot. Later on in the life-cycle of the object I need to restore the state of this object by de-serializing it and replacing the singleton. It doesn't have to be a singleton but I need to guarantee that there's only a single instance of the object.

I tried the following but it seems it only replaces it for the current request and nothing after that. I assume the DI container makes it's own copy of the object but I'm not sure

internal static SingleObject SingleObject { get; set; } = new SingleObject();

services.AddSingleton<OrderBook>(SingleObject)

Is there a way to replace the singleton instance or will I have to roll my own singleton class that handles this scenario?

3 Answers

I would invite you to read How to configure services based on request in ASP.NET Core.

After that (container being built), the registrations can't be changed anymore. @Tseng

You can only register scopes once during startup, so you could register functions related to what you want to update/refresh later on. I would recommend if you have something that needs to change implementing a cache or in memory storage that you trigger a refresh when desired.

I had a singleton of CachedData until realized needed to fast reset it at some point. So just implemented a wrapper (see below). Now the wrapper ResettableCachedData is singleton, and CachedData is transient. At any time a can do a quick Reset() to recreate CachedData, while accessing it's data via ResettableCachedData.Data.

    public class ResettableCachedData
    {
        private readonly IServiceProvider _services;

        public ResettableCachedData(IServiceProvider services)
        {
            _services = services;

            Reset();
        }

        public CachedData Data { get; protected set; }

        public void Reset()
        {
            Data = _services.GetRequiredService<CachedData>();
        }
    }

From https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2:

Singleton

Singleton lifetime services are created the first time they're requested (or when ConfigureServices is run and an instance is specified with the service registration). Every subsequent request uses the same instance. If the app requires singleton behavior, allowing the service container to manage the service's lifetime is recommended. Don't implement the singleton design pattern and provide user code to manage the object's lifetime in the class.

So, you don't need to implement the Singleton pattern your self. The DI takes care of that.

The only thing you should do now is injecting it.

Register as follow:

services.AddSingleton<SingleObject>(new SingleObject())

Related