Injecting a Factory Service in ASP.NET Core

As one of the original patterns outlined in the book “Design Patterns: Elements of Reusable Object-Oriented Software” by the “Gang of Four”, the factory pattern is the go to pattern for constructing new objects.  Aside from the singleton pattern, it is probably the most popular.  Removing the direct interaction with constructors and the ‘new’ keyword, the factory pattern allows for the dependence on interfaces as opposed to specific implementations.  Also, construction concerns (including injecting dependencies) is encapsulated when using the factory pattern.

factory

As the usage of IOC Containers has gained popularity over the years, I’ve seen the factory pattern used less and less. But even in the world of IOC containers like Microsoft.DependencyInjection, Unity, Autofac, etc. the factory pattern still has many benefits.

Let’s take a practical look at implementing the factory pattern in ASP.NET Core using the new built-in container.

Service Registration

The first step in using an IOC container is registering all interfaces and service types. There are several extension methods that are provided out of the box.

  • AddTransient – Each time a transient object is requested, a new instance will be created.
  • AddScoped – The same object will be used when requested within the same request.
  • AddSingleton – The same object will always be used across all requests.

With each of these, our dependency is provided directly.  With a factory though, we want to be able to retrieve our dependency on demand.  As such, none of these extension methods will suit our needs. For registering a factory, a custom extension method can be created.


public static class ServiceCollectionExtensions
{
public static void AddFactory<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
services.AddTransient<TService, TImplementation>();
services.AddSingleton<Func<TService>>(x => () => x.GetService<TService>());
}
}

Now when configuring the container, we can call the AddFactory function to configure our factory.


// Removed for brevity
namespace JrTech.AspNetCore.Web
{
public class Startup
{
// Removed for brevity
public void ConfigureServices(IServiceCollection services)
{
services.AddFactory<IRandomNumberGenerator, RandomNumberGenerator>();
services.AddMvc();
}
// Removed for brevity
}
}

Dependency Injection

Now with our container setup, we can inject Func<T>.


using Microsoft.AspNetCore.Mvc;
using System;
namespace JrTech.AspNetCore.Web.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly Func<IRandomNumberGenerator> _numberGeneratorFactory;
public ValuesController(Func<IRandomNumberGenerator> numberGeneratorFactory)
{
_numberGeneratorFactory = numberGeneratorFactory;
}
// GET api/values
[HttpGet]
public string Get()
{
var generator = _numberGeneratorFactory();
return $"randomNumber – {generator.Get()}" ;
}
}
}

This gives a few key benefits. Instantiation of our dependency is delayed allowing us to control when the object is initialized. If IDisposable is implemented, we can use the dependency within a using statement. The best part is we can do all of these things without interacting with the container directly.

Using a Factory Type

If we wanted to take this a step further, instead of using a Func as our factory, we could create an explicit factory type IFactory<T>.


public class Factory<T> : IFactory<T>
{
private readonly Func<T> _initFunc;
public Factory(Func<T> initFunc)
{
_initFunc = initFunc;
}
public T Create()
{
return _initFunc();
}
}

To accommodate for the new factory interface, we just need to make some slight modifications to our extension method.


public static class ServiceCollectionExtensions
{
public static void AddFactory<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
services.AddTransient<TService, TImplementation>();
services.AddSingleton<Func<TService>>(x => () => x.GetService<TService>());
services.AddSingleton<IFactory<TService>, Factory<TService>>();
}
}

Now when we inject our dependency, it is more clear what the intent is.


using Microsoft.AspNetCore.Mvc;
namespace JrTech.AspNetCore.Web.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IFactory<IRandomNumberGenerator> _numberGeneratorFactory;
public ValuesController(IFactory<IRandomNumberGenerator> numberGeneratorFactory)
{
_numberGeneratorFactory = numberGeneratorFactory;
}
// GET api/values
[HttpGet]
public string Get()
{
var generator = _numberGeneratorFactory.Create();
return $"randomNumber – {generator.Get()}" ;
}
}
}

What About Other Containers?

So now that you are convinced injecting a factory can be useful, what if you are not using the Microsoft.DependencyInjection container? Well, you might be in luck.  Many containers, such as the ones listed below, support injecting factories as Func<TService> without any customizations at all.

  • StructureMap(Lamar)
  • AutoFac
  • Ninject

Summary

Even in a world of dependency injection, the factory pattern still has its place.  By injecting a factory, you get total control of the creation of your dependencies.  With a few customization, ASP.NET Core will easily accommodate!