Click here to Skip to main content
13,551,695 members
Click here to Skip to main content
Add your own
alternative version

Stats

3K views
30 downloads
4 bookmarked
Posted 21 Apr 2018
Licenced CPOL

Autofac Dependency Injection in ASP.NET Core Web API 2.0 in N-Layer Architecture in C# Basic Part-01

Rate this:
Please Sign up or sign in to vote.
Autofac Dependency Injection in ASP.NET Core Web API 2.0 by in N-Layer Architecture in C# Basic Part-01

Introduction

In this article, we will learn how to implement dependency injection in ASP.NET Core Web API 2.0 by using Autofac DI framework services 2.0 in C#.

Background

Let’s ask a few questions to ourselves:

  1. What is dependency injection?
  2. Why do we need it?
  3. How do we implement it?

I hope you will be aware of D word in SOLID principle that is Dependency Injection. Dependency injection is the implementation of inversion of control.

What do we do in dependency injection register, resolve and dispose our services (either application services or data services). We get services object at runtime without using new keyword (I hope you will be aware of new keyword) & without worrying about dependency of the object.

If we want to make our application more loosely coupled and testable, then we have to use dependency injection in our application.

Let me answer the third question:

Since we are talking about Autofac dependency injection in ASP.NET Core Web API 2.0, we will plug Autofac DI framework services in ASP.NET Core pipeline. Let me tell you how.

Using Steps

Step 1

Create N-Layer application as shown in the below screen shot.

Step 2

Add two files "IDataRepository.cs" and "DataRepository.cs" in "DataAccess.Layer" project and add two files in "IDataService.cs" and "DataService.cs" in "Business.Layer" project.

In "IDataRepository.cs", add the below code:

namespace DataAccess.Layer
{
    public interface IDataRepository
    {
        object GetData(object obj);
        void Create(object obj);
        void Update(int id);
        void Delete(int id);
    }
}

In "DataRepository.cs", add the below code:

namespace DataAccess.Layer
{
    public class DataRepository : IDataRepository
    {
        public void Create(object obj)
        {

        }

        public void Delete(int id)
        {

        }

        public object GetData(object obj)
        {
            return obj;
        }

        public void Update(int id)
        {

        }
    }
}

In "IDataService.cs", add the below code:

namespace Business.Layer
{
    public interface IDataService
    {
        object FetchData(object obj);
    }
}

In "DataService.cs" add the below code:

using DataAccess.Layer;

namespace Business.Layer
{
    public class DataService : IDataService
    {
        private readonly IDataRepository dataRepository;
        public DataService(IDataRepository dataRepository)
        {
            this.dataRepository = dataRepository;
        }

        public object FetchData(object obj)
        {
            return this.dataRepository.GetData(obj);
        }
    }
}

Step 3

Add two nuget packages in "ASPNETWEBAPI2.Client" project from "Package Manager Console" window from below commands. You can find Package Manager Console window from Visual Studio menu = > Tools => Nuget Package Manager =>Package Manager Console.

PM > Install-Package Autofac -Version 4.7.0
PM > Install-Package Autofac.Extensions.DependencyInjection -Version 4.2.2

You can see Package Manager Console in the below screen shot:

And run both the above commands as shown in the below screen shot:

Step 5

Add the below code in "Startup.cs" in "ASPNETWEBAPI2.Client" project.

using Autofac;
using Autofac.Extensions.DependencyInjection;
using Business.Layer;
using DataAccess.Layer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace ASPNETWEBAPI2.Client
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.


        //public void ConfigureServices(IServiceCollection services)
        //{
        //    services.AddMvc();
        //    //Register application & data  services
        //    ConfigureServicesTransientLifetime(services);
        //    //ConfigureServicesSingletonLifetime(services);
        //    //ConfigureServicesScopedLifetime(services);
        //}
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            //Create Autofac ContainerBuilder 
            var containerBuilder = new ContainerBuilder();
            var container = ConfigureServicesInstancePerDependency(containerBuilder, services);
            //var container = ConfigureServicesSingleInstance(containerBuilder, services);
            //var container = ConfigureServicesInstancePerLifetimeScope(containerBuilder, services);
            //var container = ConfigureServicesInstancePerMatchingLifetimeScope
            //                (containerBuilder, services);
            //var container = ConfigureServicesInstancePerRequest(containerBuilder, services);
            //var container = ConfigureServicesInstancePerOwned(containerBuilder, services);
            //var container = ConfigureServicesThreadScope(containerBuilder, services);
            //Create Autofac Service Provider & assign Autofac container 
            var autofacServiceProvider = new AutofacServiceProvider(container);
            //Finally return Autofac Service Provider.
            return autofacServiceProvider;
        }

        private IContainer ConfigureServicesInstancePerDependency
              (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines 
            //because Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerDependency();
            containerBuilder.RegisterType<DataService>().As<IDataService>().InstancePerDependency();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
            var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }
        private IContainer ConfigureServicesSingleInstance
                (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines 
            //because Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).SingleInstance();
            containerBuilder.RegisterType<DataService>().As<IDataService>().SingleInstance();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
            var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }
        private IContainer ConfigureServicesInstancePerLifetimeScope
               (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines 
            //because Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerLifetimeScope();
            containerBuilder.RegisterType<DataService>().As<IDataService>().InstancePerLifetimeScope();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            IDataRepository dataRepositoryObjectOne;
            IDataRepository dataRepositoryObjectTwo;

            using (var scope = container.BeginLifetimeScope())
            {
                dataRepositoryObjectOne = container.Resolve<IDataRepository>();

                IDataService dataServiceObjectOne = container.Resolve<IDataService>();
                IDataService dataServiceObjectTwo = container.Resolve<IDataService>();

                var dataServiceObjectTwoResult = object.ReferenceEquals
                                              (dataServiceObjectOne, dataServiceObjectTwo);
            }

            using (var scope = container.BeginLifetimeScope())
            {
                dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
            }

            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }
        private IContainer ConfigureServicesInstancePerMatchingLifetimeScope
                    (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines because 
            //Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerMatchingLifetimeScope("WebAPI2.0Request");
            containerBuilder.RegisterType<DataService>().As
                         <IDataService>().InstancePerMatchingLifetimeScope("WebAPI2.0Request");
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            IDataRepository dataRepositoryObjectOne;
            IDataRepository dataRepositoryObjectTwo;

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectOne = scope.Resolve<IDataRepository>();
                using (var childScope = scope.BeginLifetimeScope())
                {
                    dataRepositoryObjectTwo = childScope.Resolve<IDataRepository>();

                    IDataService dataServiceObjectOne = childScope.Resolve<IDataService>();
                    IDataService dataServiceObjectTwo = childScope.Resolve<IDataService>();

                    var dataServiceObjectTwoResult = object.ReferenceEquals
                                                     (dataServiceObjectOne, dataServiceObjectTwo);

                }
                var dataRepositoryObjectResult = object.ReferenceEquals
                                                (dataRepositoryObjectOne, dataRepositoryObjectTwo);
            }

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            }

            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);
            // This will throw an exception because this scope doesn't
            // have any expected BeginLifetimeScope tag and neither does any parent scope!
            //using (var scope = container.BeginLifetimeScope())
            //{
            //    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            //}
            return container;
        }
        private IContainer ConfigureServicesInstancePerRequest
                          (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines because 
            //Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerRequest("WebAPI2.0Request");
            containerBuilder.RegisterType<DataService>().As
                     <IDataService>().InstancePerRequest("WebAPI2.0Request");
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            IDataRepository dataRepositoryObjectOne;
            IDataRepository dataRepositoryObjectTwo;

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectOne = scope.Resolve<IDataRepository>();
                using (var childScope = scope.BeginLifetimeScope())
                {
                    dataRepositoryObjectTwo = childScope.Resolve<IDataRepository>();

                    IDataService dataServiceObjectOne = childScope.Resolve<IDataService>();
                    IDataService dataServiceObjectTwo = childScope.Resolve<IDataService>();

                    var dataServiceObjectTwoResult = object.ReferenceEquals
                                    (dataServiceObjectOne, dataServiceObjectTwo);
                }
                var dataRepositoryObjectResult = 
                    object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);
            }

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            }

            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);
            // This will throw an exception because this scope doesn't
            // have any expected BeginLifetimeScope tag and neither does any parent scope!
            //using (var scope = container.BeginLifetimeScope())
            //{
            //    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            //}
            return container;
        }
        private IContainer ConfigureServicesInstancePerOwned
                    (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            return containerBuilder.Build();
        }

        private IContainer ConfigureServicesThreadScope
                    (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            return containerBuilder.Build();
        }

        // This method gets called by the runtime. 
        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }
}

If you see the above code, we can register our services by any below given registration methods:

  1. Instance Per Dependency
  2. Single Instance
  3. Instance Per Lifetime Scope
  4. Instance Per Matching Lifetime Scope
  5. Instance Per Request
  6. Instance Per Owned
  7. Thread Scope

We will learn only the first four registration methods in this article and the rest of methods will be discussed in the next article . So again, one more question is coming in our mind as to why there is more than one method to register services. Answer is to maintain the lifetime of services object. We can decide which registration method should be used as per requirement .

Let's talk about these registration methods' lifetime.

Instance Per Dependency (InstancePerDependency)

Registered service object created each time they are requested. It works best for lightweight, stateless services. It is just like Transient services in another DI.

public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            //Create Autofac ContainerBuilder 
            var containerBuilder = new ContainerBuilder();
            var container = ConfigureServicesInstancePerDependency(containerBuilder, services);
            var autofacServiceProvider = new AutofacServiceProvider(container);
            //Finally return Autofac Service Provider.
            return autofacServiceProvider;
        }

        private IContainer ConfigureServicesInstancePerDependency
               (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines 
            //because Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerDependency();
            containerBuilder.RegisterType<DataService>().As<IDataService>().InstancePerDependency();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
            var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }

From the above code, we can understand what exactly InstancePerDependency service object lifetime is.

Let's try to understand from the above code: we can see in the method "ConfigureServicesInstancePerDependency". We are creating two instances of IDataRepository, i.e., dataRepositoryObjectOne & dataRepositoryObjectTwo and verifying both objects references are equal or not.

var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

Output of result will be false in this case.

It means:

  1. Object is created each time it is requested (for example, dataRepositoryObjectOne & dataRepositoryObjectTwo in the above code)
  2. Objects are not the same, i.e., different.

Single Instance (SingleInstance)

Registered service object created once per application. object will be created with initial request and used by subsequent request in the entire lifetime of the application, i.e., we can say every service object will be the same.

public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            //Create Autofac ContainerBuilder 
            var containerBuilder = new ContainerBuilder();
            var container = ConfigureServicesSingleInstance(containerBuilder, services);
            //Create Autofac Service Provider & assign Autofac container 
            var autofacServiceProvider = new AutofacServiceProvider(container);
            //Finally return Autofac Service Provider.
            return autofacServiceProvider;
        }
       
private IContainer ConfigureServicesSingleInstance
      (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            //containerBuilder.RegisterModule<AutofacInstancePerDependencyModule>();
            //Above lines are equals to below lines 
            //because Instance Per Dependency is default lifecycle.
            //Also called 'transient or 'factory' in other containers. 
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).SingleInstance();
            containerBuilder.RegisterType<DataService>().As<IDataService>().SingleInstance();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
            var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }

Let's try to understand from the above code: you can see in the method "ConfigureServicesSingleInstance", we are creating two instances of IDataRepository, i.e., dataRepositoryObjectOne & dataRepositoryObjectTwo and verifying both objects reference are equal or not.

var dataRepositoryObjectOne = container.Resolve<IDataRepository>();
var dataRepositoryObjectTwo = container.Resolve<IDataRepository>();
var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

Output of result will be true in this case.

It means:

  1. Object created at the time of first request and used in subsequent request in entire lifetime of the application (for example, dataRepositoryObjectOne & dataRepositoryObjectTwo in the above code)
  2. Objects are the same (for example, dataRepositoryObjectOne & dataRepositoryObjectTwo are the same)

Instance Per Lifetime Scope (InstancePerLifetimeScope)

Registered service object created single instance per scope, i.e., object will be created for scope with initial request and used by subsequent request in same scope, i.e., we can say every service object will be the same for same scope.

public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            //Create Autofac ContainerBuilder 
            var containerBuilder = new ContainerBuilder();
            var container = ConfigureServicesInstancePerRequest(containerBuilder, services);        
            //Create Autofac Service Provider & assign Autofac container 
            var autofacServiceProvider = new AutofacServiceProvider(container);
            //Finally return Autofac Service Provider.
            return autofacServiceProvider;
       }  

private IContainer ConfigureServicesInstancePerLifetimeScope
            (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerLifetimeScope();
            containerBuilder.RegisterType<DataService>().As<IDataService>().InstancePerLifetimeScope();
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            IDataRepository dataRepositoryObjectOne;
            IDataRepository dataRepositoryObjectTwo;

            using (var scope = container.BeginLifetimeScope())
            {
                dataRepositoryObjectOne = scope.Resolve<IDataRepository>();

                IDataService dataServiceObjectOne = scope.Resolve<IDataService>();
                IDataService dataServiceObjectTwo = null;
                bool dataServiceObjectResult;

                for (var i = 0; i < 5; i++)
                {
                    dataServiceObjectTwo = scope.Resolve<IDataService>();
                    dataServiceObjectResult = object.ReferenceEquals
                                              (dataServiceObjectOne, dataServiceObjectTwo);
                }

                using (var childScope = container.BeginLifetimeScope())
                {
                    dataServiceObjectTwo = childScope.Resolve<IDataService>();
                    dataServiceObjectResult = object.ReferenceEquals
                                              (dataServiceObjectOne, dataServiceObjectTwo);
                }
            }

            using (var scope = container.BeginLifetimeScope())
            {
                dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            }

            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

            return container;
        }

Let's try to understand from the above code: you can see in the method "ConfigureServicesInstancePerLifetimeScope" that we are creating two instances of IDataRepository, i.e., dataRepositoryObjectOne & dataRepositoryObjectTwo in different scope and creating two objects of IDataService dataServiceObjectOne & dataServiceObjectTwo in the same scope and verifying both objects references are equal or not in both cases.

IDataRepository dataRepositoryObjectOne;
IDataRepository dataRepositoryObjectTwo;

using (var scope = container.BeginLifetimeScope())
{
    dataRepositoryObjectOne = scope.Resolve<IDataRepository>();

    IDataService dataServiceObjectOne = scope.Resolve<IDataService>();
    IDataService dataServiceObjectTwo = null;
    bool dataServiceObjectResult;

    for (var i = 0; i < 5; i++)
    {
        dataServiceObjectTwo = scope.Resolve<IDataService>();
        dataServiceObjectResult = object.ReferenceEquals
                                  (dataServiceObjectOne, dataServiceObjectTwo);
    }

    using (var childScope = container.BeginLifetimeScope())
    {
        dataServiceObjectTwo = childScope.Resolve<IDataService>();
        dataServiceObjectResult = object.ReferenceEquals
                                  (dataServiceObjectOne, dataServiceObjectTwo);
    }
}

using (var scope = container.BeginLifetimeScope())
{
    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
}

var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

Output of "dataServiceObjectResult" will be true every time in for loop because scope is the same. But in child scope, it will be false because it is in different scope. "result" will be false again different scope .

It means single instance per scope.

Instance Per Matching Lifetime Scope (InstancePerMatchingLifetimeScope)

Registered service object created once per application. object will be created with initial request and used by subsequent request in entire lifetime of the application. i.e. we can say every service object will be same.

public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            //Create Autofac ContainerBuilder 
            var containerBuilder = new ContainerBuilder();           
            var container = 
               ConfigureServicesInstancePerMatchingLifetimeScope(containerBuilder, services);
            //Create Autofac Service Provider & assign Autofac container 
            var autofacServiceProvider = new AutofacServiceProvider(container);
            //Finally return Autofack Service Provider.
            return autofacServiceProvider;
        }

private IContainer ConfigureServicesInstancePerMatchingLifetimeScope
                (ContainerBuilder containerBuilder, IServiceCollection services)
        {
            //Register your module here.
            var connectionString = "MyConnectionString";
            var namedParameter = new NamedParameter("connectionString", connectionString);
            containerBuilder.RegisterType<DataRepository>().As<IDataRepository>()
                .WithParameter(namedParameter).InstancePerMatchingLifetimeScope("WebAPI2.0Request");
            containerBuilder.RegisterType<DataService>().As
                 <IDataService>().InstancePerMatchingLifetimeScope("WebAPI2.0Request");
            //Plug-In your Autofac builder in ASP.NET Core PIPLINE.
            containerBuilder.Populate(services);
            //Build Autofac container.
            var container = containerBuilder.Build();

            IDataRepository dataRepositoryObjectOne;
            IDataRepository dataRepositoryObjectTwo;

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectOne = scope.Resolve<IDataRepository>();
                using (var childScope = scope.BeginLifetimeScope())
                {
                    dataRepositoryObjectTwo = childScope.Resolve<IDataRepository>();
                    var dataRepositoryObjectResult = object.ReferenceEquals
                                      (dataRepositoryObjectOne, dataRepositoryObjectTwo);

                    IDataService dataServiceObjectOne = scope.Resolve<IDataService>();
                    IDataService dataServiceObjectTwo = scope.Resolve<IDataService>();
                    bool dataServiceObjectResult = object.ReferenceEquals
                                                   (dataServiceObjectOne, dataServiceObjectTwo);
                }                
            }

            using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
            {
                dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            }

            var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);
            // This will throw an exception because this scope doesn't
            // have any expected BeginLifetimeScope tag and neither does any parent scope!
            //using (var scope = container.BeginLifetimeScope())
            //{
            //    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
            //}
            return container;
        }

Let's try to understand from the above code: you can see in the method "ConfigureServicesInstancePerMatchingLifetimeScope", we are creating two instances of IDataRepository, i.e., dataRepositoryObjectOne & dataRepositoryObjectTwo in different tagged or named scope and creating two objects of IDataService dataServiceObjectOne & dataServiceObjectTwo in same tagged or named scope and verifying both objects reference are equal or not in both cases.

IDataRepository dataRepositoryObjectOne;
IDataRepository dataRepositoryObjectTwo;

using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
{
    dataRepositoryObjectOne = scope.Resolve<IDataRepository>();
    using (var childScope = scope.BeginLifetimeScope())
    {
        dataRepositoryObjectTwo = childScope.Resolve<IDataRepository>();
        var dataRepositoryObjectResult =
            object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

        IDataService dataServiceObjectOne = scope.Resolve<IDataService>();
        IDataService dataServiceObjectTwo = scope.Resolve<IDataService>();
        bool dataServiceObjectResult =
             object.ReferenceEquals(dataServiceObjectOne, dataServiceObjectTwo);
    }
}

using (var scope = container.BeginLifetimeScope("WebAPI2.0Request"))
{
    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
}
var result = object.ReferenceEquals(dataRepositoryObjectOne, dataRepositoryObjectTwo);

// This will throw an exception because this scope doesn't
// have any expected BeginLifetimeScope tag and neither does any parent scope!
//using (var scope = container.BeginLifetimeScope())
//{
//    dataRepositoryObjectTwo = scope.Resolve<IDataRepository>();
//}

Output of "dataRepositoryObjectResult" & "dataServiceObjectResult" will be true in "WebAPI2.0Request" tagged or named scope because tagged or named scope is the same. But result will be false because it is in different scope.

It means single instance tagged or named per scope, i.e., it is similar to the previous one, i.e., (Instance Per Lifetime Scope). But we can not create scope without tagged or named scope.

Since this article is getting longer, I will discuss the below object lifetimes in the next article.

  • Instance Per Request (InstancePerRequest)
  • Instance Per Owned (InstancePerOwned)
  • Thread Scope (InstancePerLifetimeScope)

Step 6

Add the below line of code in "ValuesController.cs" in "ASPNETWEBAPI2.Client" project .

using Business.Layer;
using Microsoft.AspNetCore.Mvc;

namespace ASPNETWEBAPI2.Client.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly IDataService dataService;
        public ValuesController(IDataService dataService)
        {
            this.dataService = dataService;
        }

        // GET api/values
        [HttpGet]
        public object Get()
        {
            return this.dataService.FetchData(new string[] { "value1", "value2" });
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

You can see in the above ValueController code we are performing constructor injection and that will be injected at runtime by framework services.

public class ValuesController : Controller
    {
        private readonly IDataService dataService;
        public ValuesController(IDataService dataService)
        {
            this.dataService = dataService;
        }
   }

You can see constructor injection from the above code that will be injected at runtime by framework services.

Step 7

Build your project and set your project "ASPNETWEBAPI2.Client" in debug or run dropdown list as below screen shot:

Now run your Web API 2.0 project and you will see screen as below screen shot but port number can be different .

Now your Web API 2.0 is ready for consumption.

Step 8

Use any rest client to test your Web API 2.0. In my case, I used Postman to make http request as below screen shot even we can verify it in Chrome browser itself because "http://localhost:62018/api/values" is get method.

In Chrome Browser:

In Postman REST Client:

From the above screen shot, we can see that we are getting response from Web API 2.0.

Congratulations! We have successfully implemented dependency injection in ASP.NET Core Web API 2.0 by using Autofac DI framework services. If you have any query concerns, do let me know or just put in the comments box and I will respond as soon as possible. I am open to discuss anything, even silly question as well. If you have any suggestions related this article, please let me know. I promise I will improve this article as much as possible.

Points of Interest

To understand the lifetime scope of created object in Autofac ID framework services are very interesting and tricky.

History

  • 21st April, 2018: Initial version

License

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

Share

About the Author

Dinesh Singh Kushwaha (Dev)
Software Developer (Senior) CBRE South Asia Pvt. Ltd.
India India
Technology Summary

Languages: C++, C#, Java, Visual Basic,Javascript , PHP
Development Tools, Methodologies & Environments: Rapid Application Design (RAD), Object-Oriented Analysis & Design (OOAD), Waterfall Approach, Spiral Approach, Prototyping Approach, Integrated Software Development, Microsoft Visual Studio , Agile Methodology ,DDD , TDD ,BDD
Software: Visual Studio 2017 , Visual Studio Core,SQL Server Management Studio 2016 , Eclipse
Systems: Unix, Windows, VAX/VMS, NeXTStep, .Net Framework
Databases: Oracle, Sybase, Access,MS SQL Server , MySQL

EDUCATION

MDU University - Rohatak , Haryana(India)
MS in Computer Science
VBS University- Jaunpur, UP (India)
BS in Math's

CERTIFICATIONS

Certified ScrumMaster® (CSM)
CSM

You may also be interested in...

Pro
Pro

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.180515.1 | Last Updated 21 Apr 2018
Article Copyright 2018 by Dinesh Singh Kushwaha (Dev)
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid