Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
public static class AutofacCompositeExtensions {
public static IRegistrationBuilder<TImplementer, ConcreteReflectionActivatorData, SingleRegistrationStyle> RegisterComposite<TImplementer>(this ContainerBuilder builder) {
var registrationBuilder = RegistrationBuilder.ForType<TImplementer>();
builder.RegisterCallback(registry => {
registrationBuilder.OnPreparing(e => {
foreach (var service in e.Component.Services.OfType<IServiceWithType>()) {
e.Parameters = e.Parameters.Concat(new[] {
new ResolvedParameter(
(p, _) => IsCollectionOf(p.ParameterType, service),
(_, c) => ResolveCollection(c, service, e.Component)
)
});
}
});
var registration = registrationBuilder.CreateRegistration();
registry.Register(registration);
registry.Registered += (sender, e) => {
foreach (var service in registration.Services) {
IComponentRegistration @default;
if (registry.TryGetRegistration(service, out @default) && @default != registration)
throw new InvalidOperationException($"Registration {e.ComponentRegistration.Activator.LimitType} has overriden the composite registration {registration.Activator.LimitType}. Please add PreserveExistingDefaults() to preserve the composite.");
}
};
});
return registrationBuilder;
}
private static bool IsCollectionOf(Type type, IServiceWithType service) {
return service.ServiceType.MakeArrayType().IsAssignableTo(type);
}
private static object ResolveCollection(IComponentContext context, IServiceWithType service, IComponentRegistration exceptRegistration) {
var otherRegistrations = context.ComponentRegistry.RegistrationsFor((Service)service).Where(r => r != exceptRegistration);
var array = otherRegistrations.Select(r => context.ResolveComponent(r, NoParameters)).ToArray();
var typed = Array.CreateInstance(service.ServiceType, array.Length);
array.CopyTo(typed, 0);
return typed;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment