Reputation: 408
I'm working on creating validation decorators for my commands, but I'm having trouble with registering the types with the Simple Injector DI container.
The case is:
DataAnnotationsCommandValidator<TCommand>
.CreateRefreshTokenCommandValidator
, which implements ICommandValidator<CreateRefreshTokenCommand>
.According to the Simple Injector documentation, one should create a CompositeCommandValidator
in cases like these. I've mimicked the implementation mentioned in the documentation, meaning that my ValidationCommandHandlerDecorator
still can have a dependency on ICommandValidator<TCommand>
instead of an IEnumerable
.
Then there is the configuration of the Simple Injector container. My configuration currently looks like this:
_container.RegisterManyForOpenGeneric(
typeof(ICommandValidator<>),
_container.RegisterAll,
typeof (ICommandValidator<>).Assembly);
_container.RegisterAllOpenGeneric(
typeof(ICommandValidator<>),
typeof(DataAnnotationsCommandValidator<>));
_container.RegisterSingleOpenGeneric(
typeof(ICommandValidator<>),
typeof(CompositeCommandValidator<>));
However, when I debug the application, only the specific validators are injected into the CompositeCommandValidator
(I'm missing the DataAnnotationsCommandValidator
). I've tried a few different configurations, but to no avail. How should I configure Simple Injector to get the correct behavior?
Upvotes: 4
Views: 595
Reputation: 172786
UPDATE for Simple Injector v4:
// Register validators as sequence
_container.Collection.Register(
typeof(ICommandValidator<>),
typeof (ICommandValidator<>).Assembly);
// Append the data annotations validator as last element to the sequence
_container.Collection.Append(
typeof(ICommandValidator<>),
typeof(DataAnnotationsCommandValidator<>));
// Register the composite that will wrap the sequence.
_container.Register(
typeof(ICommandValidator<>),
typeof(CompositeCommandValidator<>));
Original Simple Injector v2 answer:
The RegisterManyForOpenGeneric
method will only scan the assemblies for non-generic implementations of the given interface, because open-generic implementations often need special care. There are basically two options here.
Option 1:
var types = OpenGenericBatchRegistrationExtensions.GetTypesToRegister(
_container,
typeof (ICommandValidator<>),
AccessibilityOption.PublicTypesOnly,
typeof (ICommandValidator<>).Assembly)
.ToList();
types.Add(typeof(DataAnnotationsValidator<>));
_container.RegisterAll(typeof(ICommandValidator<>), types);
Here we use the GetTypesToRegister
method to find all non-generic implementations, we append the open generic type to this collection and register the whole set using RegisterAll
.
Your second option is to mix RegisterManyForOpenGeneric
with AppendToCollection
:
_container.RegisterManyForOpenGeneric(typeof(ICommandValidator<>),
_container.RegisterAll,
typeof(ICommandValidator<>).Assembly);
// using SimpleInjector.Advanced;
_container.AppendToCollection(typeof(ICommandValidator<>),
typeof(DataAnnotationsValidator<>));
Upvotes: 2