Migrating from Simple Injector to Unity
Unity is a stand-alone DI library from the Microsoft’s Patterns & Practices group. It is possibly the most widely used DI container for .NET. While it has lot’s of implicit and surprising behavior, it is perhaps the best documented DI container
in the field.
Core differences with Simple Injector
- There’s no built-in support for auto-registration. The open source project
autoregistration.codeplex.com tries to fill this gap.
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 Unity on the right-hand side.
Resolving Instances
| Simple Injector |
Unity |
| container.GetInstance<IService>(); |
container.Resolve<IService>(); |
| container.GetInstance(typeof(IService)); |
container.Resolve(typeof(IService)); |
IEnumerable<IFilter> filters =
container.GetAllInstances<IFilter>(); |
IEnumerable<IFilter> filters =
container.ResolveAll<IFilter>(); |
IEnumerable<object>
filters =
container.GetAllInstances(typeof(IFilter)); |
IEnumerable<object>
filters =
container.ResolveAll(typeof(IFilter)); |
Registration
Registration with a transient lifetime.
| Simple Injector |
Unity |
// Optional. Concrete instances can be
// resolved without registration
container.Register<RealService>(); |
// Optional. Concrete instances can be
// resolved without registration
container.RegisterType<RealService>(); |
| container.Register<IService,
RealService>(); |
container.RegisterType<IService,
RealService>(); |
container.Register<IService>(() =>
{
var log = container.GetInstance<ILogger>();
return new RealService(log);
}); |
container.Register<IService>(
new InjectionFactory(c
=>
{
var log = c.Resolve<ILogger>();
return new RealService(log);
}));
// NOTE: Factories in Unity are not type-safe. |
Registration with a singleton lifetime.
| Simple Injector |
Unity |
| container.RegisterSingle<RealService>(); |
container.RegisterType<RealService>(
new ContainerControlledLifetimeManager()); |
| container .RegisterSingle<IService,
RealService>(); |
container.RegisterType<IService,
RealService>(
new ContainerControlledLifetimeManager()); |
container.RegisterSingle<IService>(() =>
{
var log = container.GetInstance<ILogger>();
return new RealService(log);
}); |
container.Register<IService>(
new ContainerControlledLifetimeManager(),
new InjectionFactory(c
=>
{
var log = c.Resolve<ILogger>();
return new RealService(log);
}));
// NOTE: Factories in Unity are not type-safe. |
var instance =
new
RealService(new
ConsoleLogger());
container.RegisterSingle<IService>(instance); |
var instance =
new
RealService(new
ConsoleLogger());
container.RegisterInstance<IService>(instance);
|
container.RegisterAll<IFilter>(
new
XssInjectionFilter(),
new
SqlInjectionFilter(),
new
SmartFilter()
); |
container.RegisterInstance<IEnumerable<IFilter>>(
new
IFilter[]
{
new
XssInjectionFilter(),
new
SqlInjectionFilter(),
new
SmartFilter()
});
// Or
c.RegisterType<IEnumerable<IFilter>,
IFilter []>();
c.RegisterType<IFilter,
XssInjectionFilter>("a");
c.RegisterType<IFilter,
SqlInjectionFilter>("b");
c.RegisterType<IFilter,
SmartFilter>("c");
|
IEnumerable<IFilter>
filters =
FilterProvider.GetFilters();
container.RegisterAll<IFilter>(filters); |
IEnumerable<IFilter>
filters =
FilterProvider.GetFilters();
container.RegisterInstance<IEnumerable<IFilter>>(
filters); |
container.RegisterInitializer<ICommand>(cmd =>
{
cmd.SendAsync = true;
cmd.Logger =
container.GetInstance<ILogger>();
}); |
// This might not easily translate to unity. |
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 Unity.
Registration using the non-generic API.
| Simple Injector |
Unity |
container.Register(typeof(IService),
typeof(RealService)); |
container.RegisterType(typeof(IService),
typeof(RealService)); |
var types =
from asm in
AppDomain.CurrentDomain
.GetAssemblies()
from type
in asm.GetExportedTypes()
where !type.IsAbstract
where
typeof(IFilter).IsAssignableFrom(type)
select type;
container.RegisterAll<IFilter>(types); |
var types =
from asm in
AppDomain.CurrentDomain
.GetAssemblies()
from type
in asm.GetExportedTypes()
where !type.IsAbstract
where
typeof(IFilter).IsAssignableFrom(type)
select type;
foreach
(var
type in
types)
{
container.RegisterType(typeof(IFilter),
type, type.FullName);
} |
Batch registration of generic interfaces
| Simple Injector |
Unity |
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
typeof(IHandler<>).Assembly); |
// Unity has no batch registration support
// out of the box. |
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
AppDomain.CurrentDomain.GetAssemblies()); |
|
var asm =
typeof(IHandler<>).Assembly;
container.RegisterManyForOpenGeneric(
typeof(IHandler<>),
from type
in asm.GetTypes()
where !type.IsAbstract
where type.Name.EndsWith("Handler")
select type); |
|
Mapping of open generic types to an open generic implementation
| Simple Injector |
Unity |
container.RegisterOpenGeneric(
typeof(IValidator<>),
typeof(NullValidator<>)); |
container.RegisterType(
typeof(IValidator<>),
typeof(NullValidator<>));
|
typeof(IFilter).IsAssignableFrom(type)