Click here to Skip to main content
15,881,424 members
Articles / Web Development / ASP.NET / ASP.NET Core

ASP.NET Core 2.0 Dependency Injection

Rate me:
Please Sign up or sign in to vote.
3.32/5 (4 votes)
1 Sep 2017CPOL2 min read 11.2K   3   4
Use ASP.NET Core service container for dependency injection. Continue reading...

Problem

Use ASP.NET Core service container for dependency injection.

Solution

Create a service:

C#
public interface IGreetingService
    {
        string Greet(string to);
    }

    public class GreetingService : IGreetingService
    {
        public string Greet(string to)
        {
            return $"Hello {to}";
        }
    }

Inject where required, I am using the Middleware created in a previous post:

C#
public static class UseMiddlewareExtensions
    {
        public static IApplicationBuilder UseHelloWorld(this IApplicationBuilder app)
        {
            return app.UseMiddleware();
        }
    }

    public class HelloWorldMiddleware
    {
        private readonly RequestDelegate next;

        public HelloWorldMiddleware(
            RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(
            HttpContext context,
            IGreetingService greetingService)
        {
            var message = greetingService.Greet("World (via DI)");
            await context.Response.WriteAsync(message);
        }
    }

Add service to container using AddScoped() in ConfigureServices() method of Startup.cs:

C#
public void ConfigureServices(
            IServiceCollection services)
        {
            // setup dependency injection in service container
            services.AddScoped<IGreetingService, GreetingService>();
        }

        public void Configure(
            IApplicationBuilder app,
            IHostingEnvironment env)
        {
            // setup request pipeline using middleware
            app.UseHelloWorld();
        }

Let’s say your service implementation needs more complex setup, you could use the overload that accepts a factory method. Let’s say our service accepts a parameter:

C#
public class FlexibleGreetingService : IGreetingService
    {
        private readonly string sayWhat;

        public FlexibleGreetingService(string sayWhat)
        {
            this.sayWhat = sayWhat;
        }

        public string Greet(string to)
        {
            return $"{this.sayWhat} {to}";
        }
    }

We can use factory method to add this to service container:

C#
public void ConfigureServices(
            IServiceCollection services)
        {
            // setup dependency injection in service container
            services.AddScoped(factory =>
            {
                return new FlexibleGreetingService("Good Morning");
            });
        }

In case of Singleton lifetime, an additional overload accepts an instance of service:

C#
public void ConfigureServices(
            IServiceCollection services)
        {
            // setup dependency injection in service container
            services.AddSingleton(
                new FlexibleGreetingService("Good Evening"));
        }

Discussion

ASP.NET Core comes with a built-in lightweight service container. We configure our services in ConfigureServices() method of Startup.cs. As discussed in a previous post, this method runs before Configure() method, hence we can use our services when setting up any middleware (including MVC).

The default method of injection is via public constructors, which for most scenarios is considered best practice.

Service Lifetimes

Service container manages the lifetime of services added to it. Following are the methods to accomplish this:

  • AddScoped(): These services are created once per request.
  • AddTransient(): These services are created each time they are requested.
  • AddSingleton(): These services are created first time they are requested and stay the same for subsequence requests.

Note: EF should be added as Scoped or using IServiceCollection.AddDbContext, which does this behind the scenes.

Factory Methods

The above methods all have an overload to add service using a factory method. This could be useful for services that require more complex setup, for instance using Builder pattern.

Signature for these methods look like:

C#
AddScoped(Func<IServiceProvider, TService>)

Framework Services

IServiceCollection being received by ConfigureServices() has various built-in services (provided by framework), refer to ASP.NET Core documentation.

There are also some useful extension methods on IServiceCollection to add commonly used services, e.g., AddDbContext, AddIdentity, AddOptions and AddMvc.

Disposing Services

Service container will call Dispose() on all types implementing IDisposable, except for services added as instance rather than type.

Request Services

Although injecting services via constructor is considered best practice, you could also retrieve the services using GetService() method on IServiceProvider, which can be accessed via HttpContext:

C#
public class HelloDevelopersMiddleware
    {
        private readonly RequestDelegate next;

        public HelloDevelopersMiddleware(
            RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(
            HttpContext context)
        {
            var greetingService = 
                   context.RequestServices.GetService<IGreetingService>();
            var message = greetingService.Greet("Developers (via GetService)");
            await context.Response.WriteAsync(message);
        }
    }

Note: Add using statement for Microsoft.Extensions.DependencyInjection to access the generic version of GetService() method.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
GeneralLibrary for doing Multiple Dependency Injection Pin
DrSensor24-Feb-18 9:42
DrSensor24-Feb-18 9:42 
QuestionI just have one question... Pin
Dewey1-Sep-17 6:14
Dewey1-Sep-17 6:14 
Do you EVER sleep? Big Grin | :-D Big Grin | :-D Big Grin | :-D

AnswerRe: I just have one question... Pin
User 10432641-Sep-17 6:23
User 10432641-Sep-17 6:23 
AnswerRe: I just have one question... Pin
User 10432641-Sep-17 6:56
User 10432641-Sep-17 6:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.