Migrating from Simple Injector to Autofac
Autofac is a second-generation DI container which API is directly based on .NET 3.5 and modern language features. It has a well thought, consistent API, and migration to Autofac is pretty straightforward.
Core differences with Simple Injector
- Autofac separates the registration process from resolving by defining a ContainerBuilder class that generates an
Autofac.IContainer.
- By default, concrete instances can not be resolved without registration. This behavior
can be overridden.
- The registration methods lack generic type constraints, which won’t fail at compile time, but at run time. It is possible to define
an extension method that fixes this.
- Autofac will track every IDisposable component that it creates, no matter how that instance is requested.
Code Samples
The following section contains code snippets that show how to resolve and register instances with the Simple Injector on the left-hand side, and equivalent snippets for Autofac on the right-hand side.
Resolving Instances
| Simple Injector |
Autofac |
| container.GetInstance<IService>(); |
container.Resolve<IService>(); |
| container.GetInstane(typeof(IService)); |
container.Resolve(typeof(IService)); |
| IEnumerable<IFilter> filters = container.GetAllInstances<IFilter>(); |
IEnumerable<IFilter>
filters =
container.Resolve<IEnumerable<IFilter>>(); |
IEnumerable<object>
filters = container
.GetAllInstances(typeof(IFilter)); |
Type
collectionType = typeof(IEnumerable<>)
.MakeGenericType(typeof(IFilter));
IEnumerable filters = (IEnumerable)
container.Resolve(collectionType); |
Registration
Registration with a transient lifetime.
| Simple Injector |
Autofac |
// Optional. Concrete instances can be
// resolved without registration
container.Register<RealService>(); |
// Required. Concrete instances will not
// be resolved without registration.
builder.RegisterType<RealService>(); |
| container.Register<IService,
RealService>(); |
builder.RegisterType<RealService>()
.As<IService>(); |
container.Register<IService>(() =>
{
var logger =
container.GetInstance<ILogger>();
return new RealService(logger);
}); |
builder.Register<IService>(container =>
{
var logger =
container.Resolve<ILogger>();
return new
RealService(logger);
}); |
Registration with a singleton lifetime.
| Simple Injector |
Autofac |
| container.RegisterSingle<RealService>(); |
builder.RegisterType<RealService()
.SingleInstance(); |
container
.RegisterSingle<IService,
RealService>(); |
builder.RegisterType<RealService>()
.As<IService>().SingleInstance(); |
container.RegisterSingle<IService>(() =>
{
var log = container.GetInstance<ILogger>();
return new RealService(log);
}); |
builder.Register<IService>(container =>
{
var log = container.Resolve<ILogger>();
return new RealService(log);
}).SingleInstance(); |
container.RegisterSingle<IService>(
new
RealService(new
ConsoleLogger())); |
builder.Register<IService>(container =>
{
return new RealService(new
ConsoleLogger());
}).SingleInstance(); |
container.RegisterAll<IFilter>(
new
XssInjectionFilter(),
new
SqlInjectionFilter(),
new
SmartFilter()
); |
builder.RegisterType<XssInjectionFilter>()
.As<IFilter>().SingleInstance();
builder.RegisterType<SqlInjectionFilter>()
.As<IFilter>().SingleInstance();
builder.RegisterType<SmartFilter>()
.As<IFilter>().SingleInstance(); |
IEnumerable<IFilter>
filters =
FilterProvider.GetFilters();
container.RegisterAll<IFilter>(filters); |
IEnumerable<IFilter>
filters =
FilterProvider.GetFilters();
builder.Register<IEnumerable<IFilter>>(c
=>
filters).SingleInstance(); |
container.RegisterInitializer<ICommand>(cmd =>
{
cmd.SendAsync = true;
cmd.Logger =
container.GetInstance<ILogger>();
}); |
builder.RegisterType<ICommand>()
.OnActivating(e =>
{
e.Instance.SendAsync = true;
e.Instance.Logger =
e.Context.Resolve<ILogger>();
}); |
Advanced Scenario’s
The SimpleInjector.Extensions.dll contains extension methods for the
Container class that enable many advanced scenario’s. The section below how the registrations done with the
Extensions library maps to those of Autofac.
Registration using the non-generic API.
| Simple Injector |
Autofac |
container.Register(typeof(IService),
typeof(RealService)); |
builder.Register(typeof(RealService))
.As(typeof(IService)); |
container.RegisterAll<IFilter>(
from asm
in AppDomain.CurrentDomain
.GetAssemblies()
from type
in asm.GetExportedTypes()
where !type.IsAbstract
where
typeof(IFilter).IsAssignableFrom(type)
select type); |
builder.RegisterAssemblyTypes(
AppDomain.CurrentDomain.GetAssemblies())
.Where(type => type.IsPublic)
.As<IFilter>(); |
Batch registration of generic interfaces
| Simple Injector |
Autofac |
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
typeof(IHandler<>).Assembly); |
builder.RegisterAssemblyTypes(
typeof(IHandler<>).Assembly)
.AsClosedTypesOf(typeof(IHandler<>)); |
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
AppDomain.CurrentDomain.GetAssemblies()); |
builder.RegisterAssemblyTypes(
AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandler<>)); |
var asm =
typeof(IHandler<>).Assembly;
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
from type
in asm.GetTypes()
where !type.IsAbstract
where type.Name.EndsWith("Handler")
select type); |
var asm =
typeof(IHandler<>).Assembly;
builder.RegisterAssemblyTypes(asm)
.Where(t => t.Name.EndsWith("Handler"))
.AsClosedTypesOf(typeof(IHandler<>)); |
Mapping of open generic types to an open generic implementation
| Simple Injector |
Autofac |
container.RegisterOpenGeneric(
typeof(IValidator<>),
typeof(NullValidator<>)); |
builder.RegisterGeneric(
typeof(NullValidator<>))
.As(typeof(IValidator<>)); |
typeof(IFilter).IsAssignableFrom(type)