Mixing Dependency Injection with the Singleton Design Pattern
Asked Answered
E

2

7

I have a Singleton in my Project looking like this:

//Create a Singleton
static MySingleton Instance;
private static readonly object Padlock = new object();
/// <summary>
/// Singelton Method, to make sure only one instance of this class exists at runtime.
/// </summary>
/// <returns></returns>
public static MySingleton GetInstance()
{
  //Thread Safety
  lock (Padlock)
  {
    if (Instance == null)
    {
      Instance = new MySingleton();
    }
    return Instance;
  }
}

private MySingleton()
{
}

//[...]

The Singleton contains several other classes as Properties, which should never be null.

Normally I'd use DependencyInjection to gurantee each new object gets all necessary parameters on instantiation. Like this:

IHelperClass Helper {get; set;}

IExectiveClass Executive {get; set;}

public NotMySingleton(IHelperclass helper, IExecutiveClass executive)
{
    Helper = helper;
    Executive = executive;
}

But I have no idea how to combine DependencyInjection with a Singleton Pattern.

Is there a way to use Singletons with DependenyInjection? What is common practice? What alternatives do I have (if this is not a suitable option)?

Eliaseliason answered 30/4, 2020 at 10:55 Comment(1)
The Singleton Design pattern is incompatible with Dependency Injection. You should instead inject MySingleton into the constructor of any consumer that depends on it.Eddyede
O
5

All DI frameworks provide a way to define the lifetime of objects instantiated by the DI container. One lifetime scope is usually Singleton.

If you let the DI framework control the lifetime of your MySingleton, DI will just work.

One remark though, any class which gets injected into the singleton will also be a singleton, no matter how the scope of those dependencies was defined.

If you cannot use or don't want to use the DI framework to create your MySingleton instance, one way to achieve the same would be to make the DI container available and resolve whatever the instance needs from the DI container, manually. Some might consider this an antipattern though.

Orthostichy answered 30/4, 2020 at 10:59 Comment(0)
M
0

Using a DI framework that provides a DI container would be the way to go, however for cases where this is not possible, perhaps one can use the GetInstance() method to inject the dependencies.

Something like this.

//Create a Singleton
static MySingleton Instance;
private static readonly object Padlock = new object();

//The method that would be used by production code to use the class.
public static MySingleton GetInstance()
{
    if (Instance != null)
    {
        return Instance;
    }

    IDependentService srv = new ConcreteService();
    return GetInstance(srv);
}

//The method that allows for injecting dependencies for unit testing.
public static MySingleton GetInstance(IDependentService service)
{
  if (Instance == null)
  {
      lock (Padlock)
      {
        if (Instance == null)
        {
          Instance = new MySingleton(service);
      }
  }

  return Instance;
}

private MySingleton(IDependentService service)
{
    //...
}
Malissamalissia answered 1/11, 2022 at 10:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.