How can I register a generic decorator using Castle Windsor?

前端 未结 2 2026

I need decorate all based onICommandHandler types using a corresponding DeadlockRetryCommandHandlerDecorator type

I tried

相关标签:
2条回答
  • 2020-12-01 20:52

    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);
    }
    
    0 讨论(0)
  • 2020-12-01 20:56

    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.

    0 讨论(0)
提交回复
热议问题