Dependency injection is built-in with .NET Core. Microsoft.Extensions.DependencyInjection is a framework that is an essential part for ASP.NET Core, but can be used with other application types such as console applications, WPF, UWP, and also Xamarin. This article shows the core functionality of this new framework using a simple console application.

See the new version of this article – It’s all in the Host Class – Dependency Injection with .NET

Dependency Injection

Inversion of Control

Inversion of control is a design principle where – as the name says – the one who has control is inverted. Instead of a method (typically one within a library) that defines the complete functionality on its own, the caller can supply code. This code in turn is invoked by the called method.

Using .NET, inversion of control can be implemented by using delegates or interfaces.

The following sample code shows inversion of control in action using constructor dependency injection. With the constructor of the HelloController class, an object implementing IGreetingService is injected. This object is remembered in a readonly variable, and used within the Action method:

public class HelloController
{
  private readonly IGreetingService _greetingService;
  public HelloController(IGreetingService greetingService)
  {
    _greetingService = greetingService ?? throw new ArgumentNullException(nameof(greetingService));
  }

  public string Action(string name) =>
    _greetingService.Greeting(name);
}

The interface IGreetingService itself just defines the Greeting method. This interface is all what needs to be known by the HelloController class, this class doesn’t need to know anything about the concrete implementation of this interface.

public interface IGreetingService
{
  string Greeting(string name);
}

Inversion of control is also known by the name “Hollywood principle” – don’t call us, we’ll call you.

Injecting the Service

The caller using the HelloController class has the responsibility to inject a concrete implementation for the interface IGreetingService. The implementation that will be used is defined by the type GreetingService:

public class GreetingService : IGreetingService
{
  public string Greeting(string name)
  {
    if (name == null) throw new ArgumentNullException(nameof(name));
    return $"Hello, {name}";
  }
}

The class GreetingService implements the required interface and thus can be used to pass it to the constructor of the HelloController. This is also known by the principle dependency injection, a dependency is injected. The sample code injects the service object into the constructor of the HelloController:

IGreetingService service = new GreetingService();
var controller = new HelloController(service);
string greeting = controller.Action("Matthias");
WriteLine(greeting);

With dependency injection, a dependency such as a type implementing the IGreetingService is injected.

Microsoft.Extensions.DependencyInjection

Instead of injecting the dependencies on your own, you can also use a dependency injection container.
.NET Core brings its own dependency injection container – Microsoft.Extensions.DependencyInjection. This container is used from ASP.NET Core, and can also be used with UWP and applications using the full .NET Framework, such as WPF.

Using a Container

To use this framework, you just need to add the NuGet package Microsoft.Extensions.DependencyInjection. First, the services that should be injected are collected. The ServiceCollection class keeps a list of the services, and returns a IServiceProvider object that can be used to access the registered services. Several extension methods can be used to register services: AddSingleton, AddTransient, and AddScoped.

private static void RegisterServices()
{
  var services = new ServiceCollection();
  services.AddSingleton();
  services.AddTransient();
  Container = services.BuildServiceProvider();
}

public static IServiceProvider Container { get; private set; }

Using Singleton Objects

The dependency for IGreetingService is registered as a singleton using AddSingleton. This gives the information to the container to always return the same instance when it is asked for. The dependency injection container keeps a ServiceDescriptor for each registered object which holds information about the implementation instance, the service type, the implementation type, and the service lifetime. You can also pass a factory method that is used to instantiate the object. The ServiceLifetime is an enumeration that can be one of the values Singleton, Scoped, and Transient.

Using Transient Objects

The HelloController is registered using AddTransient. With AddTransient, always a new object is created when it is retrieved from the container.

Scoped Objects

There’s also something between singleton and transient: scoped. With scoped, always the same object is retrieved within the same scope, but from another scope a different object. What’s a scope? With ASP.NET Core applications, a scope is a single Web request. If the same type is retrieved from within the same request (e.g. from different controllers, services, or views), always the same object is returned. However, different Web requests get other instances.

Service and Implementation Types

My sample code used generic methods to pass the service and implementation types. Invoking the method AddSingleton, the implementation type GreetingService is specified to be instantiated for the service type IGreetingService. When the type IGreetingService is requested, a GreetingService instance is returned. You can also specify just the implementation type, like shown with the AddTransient method. This way, the HelloController needs to be requested, and a HelloController is returned.

The methods AddSingleton, AddTransient, and AddScoped are not really defined by the ServiceCollection class. The ServiceCollection class just defines an indexer to get and set registered services, to insert and remove services, and to check if a service is registered. AddSingleton, AddTransient, and AddScoped are implemented as extension methods. A lot more extension methods are available, e.g. extension methods that allow passing an implementation factory.

Retrieving Objects from the Container

Now is the time to get objects from the container. This can be done easily using the GetService method of the IServiceProvider. Remember, the constructor of the HelloController requires an object implementing IGreetingService. There’s no need to deal with this, the dependency injection container knows how this type can be resolved – by returning a single instance of the type GreetingService.

  var controller = Container.GetService();
  string greeting = controller.Action("Stephanie");
  WriteLine(greeting);

The Managed Extensibility Framework (MEF) can be used for dependency injection as well. MEF supports to inject dependencies using attributes or programmatically.

Why?

What’s the advantage of using dependency injection? One advantage is for easier unit testing. For example, creating unit tests for the HelloController you wouldn’t want to test dependencies such as accessing the database or calling services. With dependency injection, it’s easy to mock the dependencies and create separate types that are used for the test.
Another advantage is to create independence from specific technologies. For example, you can create a view-model using .NET Core libraries, and concrete implementations of services using WPF, UWP, and Xamarin. The concrete implementation comes from the caller which is the executable, while the contracts and view-models can be implemented technology agnostic.

More Information

A larger sample using Microsoft.Extensions.DependencyInjection is shown in my blog with Using .NET Core Libraries from UWP. More samples are in the book Professional C# 7 and .NET Core 2.0. Chapter 20 is fully dedicated to dependency injection. Chapter 34, Patterns with XAML Apps shows the Microsoft.Extensions.DependencyInjection both with Xamarin and UWP. Chapters 30 to 32 use this framework with ASP.NET Core. Of course you’ll also learn more about this framework in my workshops ASP.NET Core, and MVVM.

Have fun with programming and learning,
Christian

Get the source code for this article at GitHub

20 responses to “Dependency Injection with .NET Core”

  1. […] This article gives an introduction to the Microsoft.Extensions.DependencyInjection framework: Dependency Injection with .NET Core […]

    Like

  2. […] to switch. One example where I’m using .NET Core with WPF applications now: I like the new dependency injection framework that is available with .NET Core. It is really cool. Even with tool changes coming after RTM of […]

    Like

  3. […] old today. After some years, a rewrite is useful. The new .NET Core is based on modern patterns. Dependency Injection is deeply used with .NET Core and ASP.NET […]

    Like

  4. […] This section is important for ASP.NET Web developers if you create services that are invoked by .NET clients, e.g. clients using WPF or UWP. In the chapter 31, “Patterns with XAML Apps”, the dependency injection framework Microsoft.Extensions.DependencyInjection is covered in detail. This dependency injection framework is used with ASP.NET Core applications as well that is covered in the last section of the book. For a simple example covering Microsoft.Extensions.DependencyInjection (just using a Console application), you can also read Dependency Injection with .NET Core. […]

    Like

  5. […] Data Binding with UWP Portable Library Dependency Injection Using .NET Core Libraries Professional C# – What’s in there for […]

    Like

  6. […] Data Binding with UWP Portable Library Dependency Injection Using .NET Core Libraries Professional C# – What’s in there for […]

    Like

  7. […] is Released! Portable Library, you’ll not be missed Professional C# 6 and .NET Core 1.0 RC2 Dependency Injection with .NET Core Professional C# 6 and .NET Core […]

    Like

  8. […] Dependency Injection with .NET Core […]

    Like

  9. […] sample code is based on a previous blog post Dependency Injection with .NET Core, so it’s best to read this […]

    Like

  10. […] L’injection de dépendances avec .NET Core. […]

    Like

  11. […] Microsoft.Extensions.DependencyInjection is explained in various blog posts starting with Dependency Injection with .NET Core. […]

    Like

  12. […] Microsoft.Extensions.DependencyInjection is explained in various blog posts starting with Dependency Injection with .NET Core. […]

    Like

  13. […] I can take advantage of the Host class. In this article I’m changing a previous sample from Dependency Injection with .NET Core to use the new Host class from the namespace Microsoft.Extensions.Hosting. You should read the […]

    Like

  14. […] you to stick to your favorite dependency injection framework: Autofac, Ninject, Castle Windsor, Microsoft.Extensions.DependencyInjection or any other. Our sample app uses that last one – very popular in ASP.NET […]

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About the Podcast

Welcome to Christian Nagel’s Blog by CN innovation — a place for insights, tutorials, and real-world experience in modern software development. Christian Nagel and the CN innovation team share practical knowledge about .NET, C#, Azure, ASP.NET Core, WinUI, .NET MAUI, cloud architecture, and current technology trends.