8

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?

Ryan
  • 4,354
  • 2
  • 42
  • 78
  • What do you mean by `replace the singleton instance`? You could change the singleton instance properties directly. – Edward Jan 15 '19 at 08:46
  • I can replace that value but it doesn't seem to update the value stored in the container – Ryan Jan 15 '19 at 16:15

3 Answers3

1

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>();
        }
    }
Nick Kovalsky
  • 5,378
  • 2
  • 23
  • 50
0

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.

lastlink
  • 1,505
  • 2
  • 19
  • 29
-4

From https://learn.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())

Community
  • 1
  • 1
Reuel Ribeiro
  • 1,419
  • 14
  • 23
  • 3
    Maybe I wasn't clear enough in my question but I need to be able to change the singleton value during runtime – Ryan Jan 13 '19 at 04:07
  • 2
    Once the Object is registered with the services , you should be able to change the value where-ever required.. – Soumen Mukherjee Jan 13 '19 at 15:46
  • 3
    @Atmanirbhar Bharat change the value of the properties of that object or the object itself? If the latter - how? – Pawel Sep 13 '20 at 06:40
  • Once a singleton is instantiated, it lives for the lifetime of the host. You can do whatever with its members (fields, properties, methods, etc.) but you cannot "replace" the service itself. You need a singleton container to keep a changing value, or simply access a static variable directly. – TimTIM Wong Sep 15 '21 at 00:38