Injection Dependency: Bring your own container in .NET Core console App, example with Simple Injector

Introduction of Simple Injector

Simple Injector is an easy-to-use Dependency Injection (DI) library for .NET that supports .NET Core, Xamarin, Mono and Universal apps. Simple Injector is easily integrated with frameworks such as Web API, MVC, WCF, ASP.NET Core and many others. It’s easy to implement the dependency injection pattern with loosely coupled components using Simple Injector.

Why Simple Injector? It’s simple to use, free, fast, support advanced generics types, and provide powerful diagnostics services.

If you want to know more about you can check the documentation here: https://simpleinjector.readthedocs.io/en/latest/quickstart.html

Installation of Simple Injector in a console app

Select and Install it from “Manage Nuget packages” panel

or type the following command in “Package manager console”:

PM> Install-Package SimpleInjector -Version 4.0.12

Configuration of Simple Injector in a console app

  • Import SimpleInjector and SimpleInjector.Lifestyles namespaces
  • Add a static Container property in your class Program
  • Register your service with its appropriate Interface, Simple Injector supports concrete injection (the class without its interface)
  • Optionnally add Verify method, it iterates registered service to check if something is not correct, will throw an exception before any execution of the progam
  • Then use GetInstance method to get your service

Example :

public interface IMyService
{
   string HelloWorld();
}
public class MyService: IMyService
{
   public string HelloWorld()
   {
      return "Hello world!";
   }
}
using SimpleInjector;
using System;

namespace ConsoleAppDemoWithSimpleInjector
{
   class Program
   {
      static readonly Container container;

      static Program()
      {
         container = new Container();

         container.Register<IMyService, MyService>();

         container.Verify();
      }

      static void Main(string[] args)
      {
         var service = container.GetInstance<IMyService>();
         Console.WriteLine(service.HelloWorld());
         Console.ReadLine();
      }
   }
}

Execution:

Configuration of Simple Injector in a console app thats runs undefinitely

In the absence of any framework code, you are yourself responsible to tell Simple Injector that certain code must run in isolation. This can be done with Scoping. There are two types of scoped lifestyles that can be used. ThreadScopedLifestyle allows wrapping code that runs on a single thread in a scope, where AsyncScopedLifestyle allows wrapping a block of code that flows asynchronously (using async await).

The following example demonstrates a simple Console application that runs indefinitely, and executes a request every second. The request is wrapped in a scope:

class Program
{
   static readonly Container container;

   static Program()
   {
      container = new Container();
      container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();

      container.Register<IMyService, MyService>();

      container.Verify();
   }

   static void Main(string[] args)
   {
      while (true)
      {
         using (ThreadScopedLifestyle.BeginScope(container))
         {
            var service = container.GetInstance<IMyService>();

            Console.WriteLine(service.HelloWorld());
         }

         Thread.Sleep(TimeSpan.FromSeconds(1));
      }
   }
}

By default the lifecycle of our service is Transient, it means that a new instance will be created each we ask an instance of our service, else you can set Singleton.

Transient lifestyle

container.Register<IMyService, MyService>(Lifestyle.Transient);

or

container.Register<IMyService, MyService>();

Singleton lifestyle

container.Register<IMyService, MyService>(Lifestyle.Singleton);

Example that display Guid of the instance:

public class MyService: IMyService
{
   private Guid _guid;

   public MyService()
   {
      _guid = Guid.NewGuid();
   }

   public string HelloWorld()
   {
      return $"Hello world! instance: {_guid}";
   }
}

Execution :

Transient lifestyle

Guid are not identicals

Singleton lifestyle

Guid are identicals

 

Simple isn’it ? 🙂

Entity Framework Core 2 – Breaking changes and obsolescence

 

Entity Framework Core 2 was released on August 14th. It brought new features.

On this article I will explain : Breaking changes and obsolete features

The IDbContextFacfory<T> interface was replaced by IDesignTimeDbContextFactory<T>.

This interface is required when you want to add new migration and update database.

Example:

public class AdventureWorksContextScaffoldedFactory : IDesignTimeDbContextFactory<AdventureWorksContext>
{
   public AdventureWorksContext CreateDbContext(string[] args)
   {
      var builder = new DbContextOptionsBuilder<AdventureWorksContext>();
      builder.UseSqlServer(@const.connectionStringGenerated);
      return new AdventureWorksContext(builder.Options);
   }
}

The extension method UseMemoryDatabase has changed

Now it’s strongly recommanded to use the signature with an in memory database name, because you may have issues if you use multiple databases in memory.

Example:

var serviceProvider = new ServiceCollection()
 .AddDbContextPool<AdventureWorksContext>(
    options =>
    {
       options.UseInMemoryDatabase("AdventureWorks");
    })
 .AddScoped<IEfQueries, EfQueries>()
 .BuildServiceProvider();

If you don’t use the signature with a name, you will get an “obsolete” warning:

Other changes

Package Microsoft.EntityFrameworkCore.SqlServer.Design is deprecated in favor of Microsoft.EntityFrameworkCore.Design(now provider-agnostic).

Only 2.0 providers will work, so any existing providers that target EF Core 1.x will need to be rewritten.

Logging event IDs have changed from the previous version and they are now identical to those used by corresponding ILogger messages. The logger categories now come from subclasses of DbLoggerCategory, such as DbLoggerCategory.Database.CommandDbLoggerCategory.MigrationsDbLoggerCategory.Infrastructure, etc, all of which offer a Name property.

Entity Framework Core 2 – Explicit compiled queries

 

Entity Framework Core 2 was released on August 14th. It brought new features.

On this article I will explain one of them: Explicitly compiled queries

Entity Framework Core included query caching since version 1, but there is still some overhead associated with calculating the key from the query and getting it from the cache. Therefore, version 2 introduced a capability that existed in LINQ to SQL and Entity Framework 5: explicit query compilation and execution. By this, we are able to pre-compile a query and use it in whatever context we want (of a compatible type, of course). We can even eagerly fetch associated collections or entities.

Example:

private static Func<AdventureWorksContextDI, int, Orders> _getOrderById =
  EF.CompileQuery((AdventureWorksContextDI context, int id) =>
  context.WorkOrders.Select(
  x => new Orders
  {
     Id = x.WorkOrderId,
     ProductName = x.Product.Name,
     Quantity = x.OrderQty,
     Date = x.DueDate
  }).FirstOrDefault(x => x.Id == id));

Usage:

public Orders GetOrderByIdCompiled(int id)
{
   return _getOrderById(_context, id);
}

What performance improvments to expect ?

I executed the non compiled query and the same version but compiled (using Stopwatch object), and I measured this:

  • Compiled query: 2 to 15 ms
  • Non compiled query: 4 to 23 ms

 

It looks faster 🙂