I need decorate all based onICommandHandler<T>
types using a corresponding DeadlockRetryCommandHandlerDecorator<T>
type
I tried this solution, but unfortunately it doesn't work.
container.Register(
Component.For(typeof(ICommandHandler<>))
.ImplementedBy(typeof(DeadlockRetryCommandHandlerDecorator<>)));
container.Register(
AllTypes.FromThisAssembly()
.BasedOn(typeof(ICommandHandler<>))
.WithService.Base());
How can i register a generic decorator (DeadlockRetryCommandHandlerDecorator<T>
) to wrap all generic ICommandHandler<T>
implementations?
currently this is not supported OOTB due to the fact that Windsor always favours mode specific component over an open-generic.
You can get that working quite easily with an ISubDependencyResolver
though. The code below assumes you name the component for your decorator "DeadlockRetryCommandHandlerDecorator"
public class CommandHandlerResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public FooResolver(IKernel kernel)
{
this.kernel = kernel;
}
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return (dependency.TargetType.IsGenericType &&
dependency.TargetType.GetGenericTypeDefinition() == typeof (ICommandHandler<>)) &&
(model.Implementation.IsGenericType == false ||
model.Implementation.GetGenericTypeDefinition() != typeof (DeadlockRetryCommandHandlerDecorator<>));
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return kernel.Resolve("DeadlockRetryCommandHandlerDecorator", dependency.TargetItemType);
}
}
The recommended way of achieving scenarios like that with Windsor however is by using interceptors.
I had the same issue. I managed to resolve it by registering each type explicity as more specific type. For me this solution is more clear than using sub dependency resolver
var commandTypes = businessAssembly.GetTypes()
.Where(t => !t.IsInterface && typeof(ICommand).IsAssignableFrom(t));
foreach(var commandType in commandTypes)
{
var handlerInterface = typeof(ICommandHandler<>).MakeGenericType(new[] { commandType });
var transactionalHandler = typeof(DeadlockRetryCommandHandlerDecorator<>).MakeGenericType(new[] { commandType });
container.Register(Component.For(handlerInterface)
.ImplementedBy(transactionalHandler)
.LifeStyle.PerWebRequest);
}