Variance ExtensionsΒΆ
Allowing Simple Injector to resolve a variant registration.
The following code snippet adds the ability to Simple Injector to resolve an assignable variant implementation, in case the exact requested type is not registered.
using System;
using System.Linq;
using SimpleInjector;
public static class VarianceExtensions
{
/// <summary>
/// When this method is called on a container, it allows the container to map an
/// unregistered requested (interface or delegate) type to an assignable and
/// (interface or delegate) type that has been registered in the container. When
/// there are multiple compatible types, an <see cref="ActivationException"/> will
/// be thrown.
/// </summary>
/// <param name="ContainerOptions">The options to make the registrations in.</param>
public static void AllowToResolveVariantTypes(this ContainerOptions options)
{
var container = options.Container;
container.ResolveUnregisteredType += (sender, e) =>
{
Type serviceType = e.UnregisteredServiceType;
if (!serviceType.IsGenericType || e.Handled) return;
var registrations = FindAssignableRegistrations(container, serviceType);
if (!registrations.Any())
{
// No registration found. We're done.
}
else if (registrations.Length == 1)
{
// Exactly one registration. Let's map the registration to the
// unregistered service type.
e.Register(registrations[0].Registration);
}
else
{
var names = string.Join(", ",
registrations.Select(r => r.ServiceType.ToFriendlyName()));
throw new ActivationException(string.Format(
"There is an error in the container's configuration. It is impos" +
"sible to resolve type {0}, because there are {1} registrations " +
"that are applicable. Ambiguous registrations: {2}.",
serviceType.ToFriendlyName(), registrations.Length, names));
}
};
}
private static InstanceProducer[] FindAssignableRegistrations(
Container container, Type serviceType)
{
Type serviceTypeDefinition = serviceType.GetGenericTypeDefinition();
return (
from reg in container.GetCurrentRegistrations()
where reg.ServiceType.IsGenericType
where reg.ServiceType.GetGenericTypeDefinition() == serviceTypeDefinition
where serviceType.IsAssignableFrom(reg.ServiceType)
select reg)
.ToArray();
}
}
After copying the previous code snippet to your project, you can use the extension method as follows:
var container = new Container();
container.Options.AllowToResolveVariantTypes();
// IEventHandler<in TEvent>
this.container.Register<IEventHandler<CustomerMovedEvent>, CustomerMovedEventHandler>();
// MoveCustomerAbroadEvent inherits from MoveCustomerEvent
var handler = this.container.GetInstance<IEventHandler<CustomerMovedAbroadEvent>>();
// Assert
Assert.IsInstanceOfType(handler, typeof(CustomerMovedEventHandler));