Real-time search with ASP.NET and Elasticsearch

A common problem that we are faced when we have deployed our applications is improve the performance of a page or feature.

In my case for example I had a field where I could search and select a city, so the starting elements were a lot and the search was quite slow; I wanted a better user experience.

We can solve performance problems like these with the help of a cache or a full-text search.

I have chosen the last one and elastic search as full-text engine, so I’ll describe the steps that I followed to configure and use it in my application.

Installation

The first step is install the elastic search server, that you can download here.

Once installed we have to start it by executing the following executable:

<Installation path>\bin\elasticsearch.bat

This is the server log:

log

The server will take care to index the content that we will pass to it; in order to do that we need a client to use in our application; in my case the application was .NET and I used NEST.

NEST

As said above, NEST is an elastic search high level client for .NET applications.

The first step is install it in the application with nuget:

Install-package NEST

And in the package.config we’ll have:

package

Now we have all the necessary tools and we can develop the code for the search feature.

Client

We define a client class that has one responsability, that is setup the url and the default index of the client, and that instantiate it:


public class ElasticSearchClient
{
privatereadonlyIElasticClient _client;

publicElasticSearchClient(IElasticClient client)
{
_client = client;
}

publicElasticSearchClient(string uri, string indexName) : this(CreateElasticClient(uri, indexName)) {}

publicIElasticClientGetClient()
{
return_client;
}

privatestaticElasticClientCreateElasticClient(string uri, string indexName)
{
var node = newUri(uri);
var setting = newConnectionSettings(node);
setting.DefaultIndex(indexName);
returnnewElasticClient(setting);
}
}

Once instantiated, the class returns a new instance of the client; we can register it in the startup class of the application with autofac:


public partial class Startup
{
publicvoidConfiguration(IAppBuilder app)
{
var builder = newContainerBuilder();

builder.Register(c => newElasticSearchClient("http://localhost:9200", "cities"))
.AsSelf()
.SingleInstance();
...
}
}

Service base class

A service that uses an elasticsearch index should be able to do some basic operations, that concerns the logics of the full-text indexes.

We have to deal with the initialize a specific index, populate the index with the contents, obviously performs a search on the index with specific parameters.

So, we have to define an interface like this:


internal interface IElasticSearchService<T> where T : class
{
voidInit();
voidCheckIndex();
voidBulkInsert(List<T> objects);
IEnumerable<T> Search(string query);
}

I like to separate the init method, that create the index, from the checkindex method, that check if the index already exists.

Now we can implement the basic service:


public class ElasticSearchService<T> : IElasticSearchService<T> where T : class
{
protectedreadonlyContext Db = newContext();
protectedreadonlyElasticSearchClient ElasticSearchClient;
protectedreadonlystring IndexName;

publicElasticSearchService(ElasticSearchClient elasticSearchClient, string indexName)
{
ElasticSearchClient = elasticSearchClient;
IndexName = indexName;
}

publicvirtualvoidInit()
{
CheckIndex();
BulkInsert(Db.Set<T>().ToList());
}

publicvoidCheckIndex()
{
if (IndexExist()) return;
var response = CreateIndex();

if (!response.IsValid)
{
thrownewException(response.ServerError.ToString(), response.OriginalException);
}
}

publicvoidBulkInsert(List<T> objects)
{
var response = ElasticSearchClient.GetClient().IndexMany(objects, IndexName);
if (!response.IsValid)
{
thrownewException(response.ServerError.ToString(), response.OriginalException);
}
}

publicvirtualIEnumerable<T> Search(string query)
{
var results = ElasticSearchClient.GetClient().Search<T>(c => c.From(0).Size(10).Query(q => q.Prefix("_all", query)));

returnresults.Documents;
}

protectedvirtualIResponseCreateIndex()
{
var indexDescriptor = newCreateIndexDescriptor(IndexName).Mappings(ms => ms.Map<T>(m => m.AutoMap()));
returnElasticSearchClient.GetClient().CreateIndex(indexDescriptor);
}

protectedboolIndexExist()
{
returnElasticSearchClient.GetClient().IndexExists(IndexName).Exists;
}
}

The constructor accept the client and the index name.

We define a virtual init method, that check if the index exists and do a bulkinsert of a list of object; the method is virtual, we think that a derived service could override the method.

This bulkinsert method leverage the client to index the object list and the search method implements a basic search, that searchs in all the fields of the objects by using the special field _all, which contains the concatenate values of all fields.

The method returns the first 10 elements.

Createindex create a specific index with automap option, that infers the elasticsearch fields datatypes from the POCO object that we pass to it; it’s protected, so the derived class could use it.

IndexExists check if an index exists and it can be used from the derived class as well.

Service

Now we can implement a specific service, that inherits from ElasticSearchService class.

In this example I need to search in a list of cities and related districts, so I need to override the CreateIndex method like this:


public sealed class CitiesService : ElasticSearchService<City>
{
publicCitiesService(ElasticSearchClient elasticSearchClient, string indexName): base(elasticSearchClient, indexName) {}

protectedoverrideIResponseCreateIndex()
{
var indexDescriptor = newCreateIndexDescriptor(IndexName).Mappings(
ms => ms.Map<City>(m => m.AutoMap().Properties(ps =>
ps.Nested<District>(n => n
.Name(nn => nn.District)
.AutoMap()))));

returnElasticSearchClient.GetClient().CreateIndex(indexDescriptor);
}

publicoverrideIEnumerable<City> Search(string query)
{
var results = ElasticSearchClient.GetClient().Search<City>(c => c.From(0).Size(10).Query(q => q.Prefix(p => p.Name, query) || q.Term("district.name", query)));

returnresults.Documents.OrderBy(d => d.Name);
}
}

What I need to do is automap the city object and the district, that is a closely related entity of the city; so I have to map the District property as nested with the automap option as well.

Thus I will able to search for all the properties of the city and the district.

The other method that I override is the Search method; I search partially in the name of the city (Prefix) and the specific term in the district name (Term) and I returns the first 10 elements.

Now I have to register the service with autofac:


public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = newContainerBuilder();

builder.Register(c => newElasticSearchClient("http://localhost:9200", "cities"))
.AsSelf()
.SingleInstance();

builder.Register(c => newCitiesService(c.Resolve<ElasticSearchClient>(), "cities"))
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance();

...
}
}

The last step is initialize the full text index of my service:


public partial class Startup
{
publicvoidConfiguration(IAppBuilder app)
{
var builder = newContainerBuilder();

builder.Register(c => newElasticSearchClient("http://localhost:9200", "cities"))
.AsSelf()
.SingleInstance();

builder.Register(c => newCitiesService(c.Resolve<ElasticSearchClient>(), "cities"))
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance();

...

InitElasticSearchServices(containerBuilder);
}

privatestaticvoidInitElasticSearchServices(IContainer containerBuilder)
{
var citiesServices = containerBuilder.Resolve<CitiesService>();
citiesServices.Init();
}
}

I make a new instance of the service and call the Init method of the ElasticSearchService that we have seen above.

This method will create and populate the index.

Web API

Now I can use the service in my Web API, like this:


public class CitiesController : ApiController
{
privatereadonlyCitiesService _elasticSearchService;

publicCitiesController(CitiesService elasticSearchService)
{
_elasticSearchService = elasticSearchService;
}

// GET: api/Cities
publicIEnumerable<City> GetCities(string query)
{
return_elasticSearchService.Search(query);
}

protectedoverridevoidDispose(bool disposing)
{
base.Dispose(disposing);
}
}

You can find the source code of this topic here.

Advertisements
Real-time search with ASP.NET and Elasticsearch

Register and test per-request services with Autofac

When we develop web application, like ASP.NET applications, we often need to implement a service with some informations related to the user request, such as session/account infos.

In this case, the service will be tied to the web request lifecycle and there will be an instance of the service for each request.

Autofac help us to manage the instances and the life cycles of these services.

Service

We can develop a simple service that we use for our tests:


public class AccountService
{
private ITokenService _tokenService;

public AccountService(ITokenService tokenService)
{
_tokenService = tokenService;
}
}

Module

In order to register the service, we use an Autofac module:


public class PerRequestModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AccountService>()
.AsSelf()
.InstancePerRequest()
.WithParameter(new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ITokenService),
(pi, ctx) => ctx.ResolveKeyed<ITokenService>("singletonTokenService")
));
}
}

The service was defined has InstancePerRequest; we also specified explicitly the implementation of the parameter interface.

And register it in the Autofac container:


var builder = new ContainerBuilder();
...
builder.RegisterModule(new PerRequestModule());
...
containerBuilder = builder.Build();

Test methods

Now, the last step is the test methods:


[Test]
public void should_is_not_the_same_instance_for_different_requests()
{
AccountService accountService1, accountService2;

using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
accountService1 = dependencyScope.GetService(typeof(AccountService)) as AccountService;
}

using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
accountService2 = dependencyScope.GetService(typeof(AccountService)) as AccountService;
}

ReferenceEquals(accountService1, accountService2).ShouldBeEquivalentTo(false);
}

[Test]
public void should_be_able_to_resolve_instance_per_request()
{
using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
AccountService service = dependencyScope.GetService(typeof(AccountService)) as AccountService;

service.Should().NotBeNull();
}
}

In order to be able to test a per-request service, we need an instance of the HttpRequestMessage class and set the configuration with the httpConfiguration defined in the Autofac container; then we can use the request scope to get an instance of our services and make the test.

You can find the source code here.

Register and test per-request services with Autofac

Registering of the ASP.NET MVC Controllers with Autofac

One of the capabilities of Autofac is the integration with the ASP.NET applications.

ASP.NET MVC is a framework thinked to supports the dependency injection, and so we can use Autofac to register the modules that compose the application, such as the controllers.

Therefore, let’s start by implementing the controllers of the application, then we ‘ll add the Autofac module that define the controllers registration.

Controllers

We implement two controllers, a Controller and an ApiController:

public class HomeController : Controller
 {
 LoggerService _loggerService;

public HomeController(LoggerService loggerService)
 {
 _loggerService = loggerService;
 }
 }

The second one is the Web Api:

public class AccountController : ApiController
 {
 LoggerService _loggerService;

 public AccountController(LoggerService loggerService)
 {
 _loggerService = loggerService;
 }
 }

Autofac module

The first step is install the two autofac packages needed for the integration with ASP.NET:

install-package Autofac.Integration.Mvc
install-package Autofac.Integration.WebApi

Now we can register the controllers with an Autofac module:

public class PerRequestModule : Module
 {
 protected override void Load(ContainerBuilder builder)
 {
 var controllersAssembly = Assembly.GetAssembly(typeof(HomeController));
 var apiControllersAssembly = Assembly.GetAssembly(typeof(AccountController));

 builder.RegisterControllers(controllersAssembly);
 builder.RegisterApiControllers(apiControllersAssembly);
 }
 }

By using the reflection, we can register all the controllers in one shot.

The module needs to be registered in the autofac container:

var builder = new ContainerBuilder();
....
builder.RegisterModule(new PerRequestModule());
...
containerBuilder = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(containerBuilder));

httpConfiguration = new HttpConfiguration
{
DependencyResolver = new AutofacWebApiDependencyResolver(containerBuilder)
};

We built the container and passed that to the AutofacDependencyResolver (Controller) and to the AutofacWebApiDependencyResolver (ApiController).

Tests

Now we can implement the test methods:

public class PerRequestTests : BaseTests
{
[Test]
public void should_be_able_to_resolve_mvc_controller()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var controller = scope.Resolve<HomeController>();
controller.Should().NotBeNull();
}
}

[Test]
public void should_be_able_to_resolve_api_controller()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var controller = scope.Resolve<AccountController>();
controller.Should().NotBeNull();
}
}
}

As you can see, we initialized a new lifetime scope and tried to resolve the controllers.
You can find the source code here.

Registering of the ASP.NET MVC Controllers with Autofac

Services lifetime scope with Autofac

Basically when we resolve a component with Autofac, we could register the object instance in the root container; this is not the best practice, because these components will never be disposed as long as the container lives, that normally is the lifetime of the application.

Then, the root container will hold the references until the application shutdown, and this could be cause memoty leaks.

A better approach is the using of the lifetime scopes, that help us to define an area where the service can be shared with other components and disposed at the end.

Let’s start defining the classes to be used as services in the Autofac configuration.

Services

We can use two simple class, a CustomerService class and an OrdersService:


public class CustomerService
{
public CustomerService() { }
}


public class OrdersService
{
private ITokenService _tokenService;

public OrdersService(ITokenService tokenService)
{
this._tokenService = tokenService;
}

}

The OrdersService accepts in the constructor an ITokenService and we have an implementation of that:


public class PerDependencyTokenService : ITokenService
 {
 private Guid _token { get; set; }

public Guid GetToken()
 {
 if (_token == Guid.Empty)
 _token = Guid.NewGuid();

return _token;
 }
 }

Now we can define the services registration, let’s start creating the Autofac modules.

Modules

First of all, we need to register the PerDependencyTokenService and we must identify it in order to distinguish this service from the others that implements the ITokenService interface:


public class PerDependencyModule : Module
 {
 protected override void Load(ContainerBuilder builder)
 {

builder.RegisterType<PerDependencyTokenService>()
 .AsSelf()
 .AsImplementedInterfaces()
 .Keyed<ITokenService>("perDependencyTokenService");
 }
 }

We registered the service as Keyed, and we identified that with a specific tag.

Now we can register the other services:


public class PerLifetimeScopeModule : Module
 {
 protected override void Load(ContainerBuilder builder)
 {
 builder.RegisterType<OrdersService>()
 .AsSelf()
 .InstancePerLifetimeScope()
 .WithParameter(new ResolvedParameter(
 (pi, ctx) => pi.ParameterType == typeof(ITokenService),
 (pi, ctx) => ctx.ResolveKeyed<ITokenService>("perDependencyTokenService")
 ));

// PER MATCHING LIFETIMESCOPE
 builder.RegisterType<CustomerService>()
 .AsSelf()
 .InstancePerMatchingLifetimeScope("scope1");
 }

}

OrderService is registered as InstancePerLifetimeScope, so an instance of this component will be unique in a specific scope.

We specify the Parameter ITokenService as well, and we tell to Autofac to resolve this with a specific key; so we are able to specify the concrete class that implements the ITokenService interface.

The second registration is about the CustomerService; this registration is slightly different from the first one, because we want to resolve the CustomerService only for the lifetime scopes that has a specific name.

Now we are going to implement the test methods that will use the services.

Test methods

The first step is register the module in the Autofac container:

builder.RegisterModule(new PerLifetimeScopeModule());

Then we can implement the test methods:

public class InstancePerLifetimeScopeTests : BaseTests
{
[Test]
public void should_is_not_the_same_instance_for_different_lifetime_scopes()
{
OrdersService ordersService1, ordersService2;

using (var scope = containerBuilder.BeginLifetimeScope())
{
ordersService1 = scope.Resolve<OrdersService>();
}

using (var scope = containerBuilder.BeginLifetimeScope())
{
ordersService2 = scope.Resolve<OrdersService>();
}

ReferenceEquals(ordersService1, ordersService2).ShouldBeEquivalentTo(false);
}

[Test]
public void should_not_be_able_to_resolve_instance_per_lifetime_scope()
{
CustomerService customerService1 = null, customerService2 = null;

try
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
customerService1 = scope.Resolve<CustomerService>();

using (var scope1 = containerBuilder.BeginLifetimeScope("scope1"))
{
customerService2 = scope.Resolve<CustomerService>();
}

customerService1.ShouldBeEquivalentTo(null);
}
}
catch (Exception)
{
customerService1.ShouldBeEquivalentTo(null);
}
}

[Test]
public void should_be_able_to_resolve_instance_per_lifetime_scope()
{
CustomerService customerService1, customerService2;

using (var scope = containerBuilder.BeginLifetimeScope("scope1"))
{
customerService1 = scope.Resolve<CustomerService>();

using (var scope1 = containerBuilder.BeginLifetimeScope())
{
customerService2 = scope.Resolve<CustomerService>();
}
}

ReferenceEquals(customerService1, customerService2).ShouldBeEquivalentTo(true);
}
}

In the first method, we create two different lifetime scopes and we check that the two objects have not the same reference.

In the second one, we should not be able to resolve the CustomerService for a generic lifetime scope, because we registered this service for a scope named scope1.

So this row:

customerService1 = scope.Resolve<CustomerService>();

will throw a DependencyResolutionException.

Instead in the third method will be able to resolve the service, because we try to create an instance in a LifetimeScope named scope1; and of course, this service will be single instance for every lifetime scope that match the name.

You can find the source code here.

 

Services lifetime scope with Autofac

Repository pattern with Autofac

The repository pattern is one of the most popular patterns used in the applications architecture.

With Autofac we are able to manage the dependencies and the lifecycle of the repositories in our application.

So let’s starting with the implementation of a basic respository example, then we proceed with the Autofac configurations and with the test methods.

Repository implementation

The are many choices to put into practice the repository pattern.

But this is not the main topic of this post, so we can proceed with a simple implementation:


public class Product
{
public int Code { get; set; }
public string Description { get; set; }
}

public interface IProductsRepository
{
List<Product> GetProducts();
}

public class ProductsRepository : IProductsRepository
{
private string _connectionString;
private List<Product> _products { get; set; }

public ProductsRepository(string connectionString)
{
_connectionString = connectionString;

_products = new List<Product>()
{
new Product()
{
Code = 1,
Description = "Product1"
},
new Product()
{
Code = 2,
Description = "Product2"
}
};
}

public List<Product> GetProducts()
{
return _products;
}
}

The ProductRepository implements a simple interface and has a constructor that accept a connection string parameter and populates a list of products.

In the real world the repository should use the connection string to connect to a database and retrieve the products, but in this case is easier to build an in memory list.

Now we inject this repository in the services that use it:


public class ProductsService
{
private IProductsRepository _productsRepository;
private ITokenService _tokenService;

public ProductsService(IProductsRepository productsRepository, ITokenService tokenService)
{
this._productsRepository = productsRepository;
this._tokenService = tokenService;
}

public List<Product> GetProducts()
{
List<Product> products = new List<Product>();

if (_tokenService.GetToken() != Guid.Empty)
products = _productsRepository.GetProducts();

return products;
}
}

The service has a GetProducs method that returns the list of products if a specific token is valid.

Autofac configuration

Autofac can be organized in modules, each of witch will be registered in the container.

In this case, we can implement a module for all the objects registered as PerDependency:


public class PerDependencyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
var repositoriesAssembly = Assembly.GetAssembly(typeof(ProductsRepository));
builder.RegisterAssemblyTypes(repositoriesAssembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.WithParameter(
new TypedParameter(typeof(string), ConfigurationManager.ConnectionStrings["Context"].ToString())
);
}
}

By default, Autofac registers the components as per dependency, that means that a unique instance of the object will be created for each request.

With the first row we retrieve the list of the repository objects in the assembly, by checking that in the name of the class the word Repository is present.

Then we say autofac that the object shall be registered as the implemented interface; if you remember, in the constructor of the ProductService we defined the repository parameter by using the interface and not the relative concrete class.

The last part define the parameter that the repository needs, that is the connection string.

The second module that we create is the SingleInstanceModule:


public class SingleInstancesModule : Module
{
protected override void Load(ContainerBuilder builder)
{

builder.RegisterType<ProductsService>()
.AsSelf()
.SingleInstance();
}
}

We register the ProductService as single instance because we want that only one instance for this service exists in the application.

Then we register the modules in the Autofac container.

Because we want to test the configuration, we can make a BaseTest class with NUnit, and build the container in the Setup method.


[TestFixture]
public class BaseTests
{
protected IContainer containerBuilder;
protected HttpConfiguration httpConfiguration;

[SetUp]
public void Setup()
{
var builder = new ContainerBuilder();

// SINGLE INSTANCES
builder.RegisterModule(new SingleInstancesModule());

// PER DEPENDENCY
builder.RegisterModule(new PerDependencyModule());

containerBuilder = builder.Build();
}

[TearDown]
public void TearDown()
{
containerBuilder.Dispose();
}
}

With the RegisterModule method we are able to register an entire module defined.

Test methods

Here we go, now we can implement test methods to check that our configuration is correct.

First of all, we check the ProductRepository registration:


public class PerDependencyTests : BaseTests
{

[Test]
public void should_be_able_to_resolve_instance_per_dependency()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var result = scope.Resolve<IProductsRepository>();
result.Should().NotBeNull();
}
}

[Test]
public void should_not_be_able_to_resolve_instance_per_dependency()
{
ProductsRepository repository = null;

try
{
using (var scope = base.containerBuilder.BeginLifetimeScope())
{
repository = scope.Resolve<ProductsRepository>();
repository.ShouldBeEquivalentTo(null);
}
}
catch (Exception)
{
repository.ShouldBeEquivalentTo(null);
}
}
}

For every test method we create a LifetimeScope that is useful to create a concrete instance of the repository.

In the first test method we try to resolve the IProductRepository interface, and the result is true.

In the second one, we try to resolve the concrete class, and we should not be able to do it, because, as you remember, we registered the ProductRepository as the implemented interface.

The ProductService registration test methods might look like these:


public class SingleInstanceTests: BaseTests
{

[Test]
public void should_return_the_products_list()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var productsService = scope.Resolve<ProductsService>();
var result = productsService.GetProducts();

result.Should().NotBeNull();
result.Should().NotBeEmpty();
}
}

[Test]
public void should_is_the_same_single_instance()
{
ProductsService productsService1, productsService2;

using (var scope = containerBuilder.BeginLifetimeScope())
{
productsService1 = scope.Resolve<ProductsService>();
}

using (var scope = containerBuilder.BeginLifetimeScope())
{
productsService2 = scope.Resolve<ProductsService>();
}

ReferenceEquals(productsService1, productsService2).ShouldBeEquivalentTo(true);
}
}

The first method check that a list of products is returned.

The second one verify that for different lifetime scopes, the service instance is the same.

You can find the source code here.

 

Repository pattern with Autofac

Register a singleton service with Autofac

Autofac is a popular and very useful IoC container, a tool that help us to manage the dependency injection in our application.

What we want from a IoC container is the ability to instantiate the objects needed in different contexts and situations and define configurations, without worry about who and when instantiate these objects.

Of course, the target application need to be ready to host an IoC container, that means all the components of the application will need to be able to receive their dependencies as inputs.

Moving on, one of a common cases where we use an IoC container is to manage a singleton service.

The old school did solve this situation without an IoC container, but defining the service as static and using it directly in the objects that depends upon it.

With Autofac this service will be defined as a non static object and injected in the constructor as dependence.

This is the first of series of post that I hope help to understand the power of Autofac and to discover more in detail a bunch of features useful for our applications.

Application architecture

Lets starting with the development of a example application that will using Autofac.

In this application we need to implement and share a singleton service; the scope of this service is generate a token and provide it to the dependent services.

So, the token service implement an interface:


public interface ITokenService
 {
 Guid GetToken();
 }

And the implementation is like this:

public class SingletonTokenService : ITokenService
 {
 private Guid _token { get; set; }

 public Guid GetToken()
 {
 if (_token == Guid.Empty)
 _token = Guid.NewGuid();

 return _token;
 }
 }

This is a very simple piece of code so far.

Now you can implement the ProductService, that need to use TokenService:

public class ProductsService
 {
 private IProductsRepository _productsRepository;
 private ITokenService _tokenService;

 public ProductsService(IProductsRepository productsRepository, ITokenService tokenService)
 {
 this._productsRepository = productsRepository;
 this._tokenService = tokenService;
 }

 public List<Product> GetProducts()
 {
 List<Product> products = new List<Product>();

 if (_tokenService.GetToken() != Guid.Empty)
 products = _productsRepository.GetProducts();

 return products;
 }
 }

The service receives in the constructor the dependencies objects and assign them to private objects.

The GetProducts method check if the token is valid and returns the list of products.

Now we need to configure Autofac in order to provide the services.

Autofac container

Autofac has a container builder that we use to define the rules for the objects instantiation:

var builder = new ContainerBuilder();

builder.RegisterType<SingletonTokenService>()
 .AsSelf()
 .AsImplementedInterfaces()
 .SingleInstance();

builder.RegisterType<ProductsService>()
 .AsSelf()
 .SingleInstance();

containerBuilder = builder.Build();

You can notice SingleInstance option, that means these services are singleton; furthermore, the SingleTokenService has the option AsImplementedInterface that allow to resolve all the dependencies that refer to the interface implemented by the service (in the constructor of the ProductService we refer to the interface, not to the implemented class).

Resolve the service

The last step is resolve the ProductService.

We expect that once resolved, will exist only a single instance of the service; we can make a simple test method using NUnit.

public void should_is_the_same_instance()
{
ProductsService productsService1, productsService2;

using (var scope = this.containerBuilder.BeginLifetimeScope())
{
productsService1 = scope.Resolve<ProductsService>();
}

using (var scope = this.containerBuilder.BeginLifetimeScope())
{
productsService2 = scope.Resolve<ProductsService>();
}

object.ReferenceEquals(productsService1, productsService2).ShouldBeEquivalentTo(true);
}

In order to simulate two request, we use the BeginLifeTimeScope method, that create a separate scope for the instances; with the Resolve method we tell to Autofac to resolve and create an instance of a specific object, with the rules specified in the container.

In the last row we check that the two objects have reference equality.

You can find the source code here.

Register a singleton service with Autofac