3
votes

I'm implementing dependency injection in my project. I've come across two ways to add a singleton service -

services.AddSingleton(new MyCustomService())

and

services.AddSingleton<MyCustomService>()

Both methods seem to work. What's the difference between these two methods, and which one should I be using?

3

3 Answers

3
votes

When using the generic .AddSingleton<TService>() method (and .AddSingleton<TService, TImplementation>(), the type is created, controlled, and disposed of by the container. When the constructor contains other dependencies, those dependencies are automatically injected (a technique called "Auto-Wiring").

Instances supplied using .AddSingleton<TService>(TService) already exist. In that case, the container will not dispose of that instance when it implements IDisposable or IAsyncDisposable. You are responsible for disposing of that instance yourself.

Since .AddSingleton<TService>(TService) is supplied with an already existing instance, the container can't inject any dependencies, because in order to do that, it must also create the instance.

1
votes

According to the docs in first sample, you are using AddSingleton<TService>(IServiceCollection, TService) extension method, and in second one - AddSingleton<TService>(IServiceCollection).

The difference between this 2 is the time when the instance of TService is created. In first one - you create it upon registration. In second one - it will be created be container on first request.

It's up to you which one you should use. But if your MyCustomService may have additional dependencies - I guess AddSingleton<TService>(IServiceCollection) maybe more handy.

0
votes

Short answer: explicit loading of a service versus using generics to pull from injection via configuration.

In the first instance, you are adding a SingletonService you are instantiating yourself. In the second, you are asking dependency injection to load up MyCustomService based on configuration. The latter is useful when you might have different versions of MyCustomService for different configurations of the application.

Another way of looking at it. The first is loading a singleton and fails if it is not. The second is using generics to validate the type of service and will blow up if there are none specified in configuration.