Registering generic decorators in Windsor [duplica

2019-05-05 08:53发布

问题:

This question already has an answer here:

  • How can I register a generic decorator using Castle Windsor? 2 answers

I have an interface that looks like this:

public interface IQueryHandler<in TQuery, out TResult>
    where TQuery : IQuery<TResult>
{
    TResult Handle(TQuery query);
}

I want to wrap all my handlers with this caching decorator:

public class CachingQueryHandler<TQuery, TResult>
    : IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult>
{
    public CachingQueryHandler(
        IQueryHandler<TQuery, TResult> handler,
        IQueryCachingRule<TQuery, TResult> cachingRule,
        ITaggedCacheProvider cache)
    {
        //...
    }

    //...
}

Thats how I registering components in Windsor:

container.Register(
    Component
        .For(typeof(IQueryHandler<,>))
        .ImplementedBy(typeof(CachingQueryHandler<,>)),
    Classes
        .FromAssemblyContaining<GetUserCourseStatesHandler>()
        .BasedOn(typeof(IQueryHandler<,>))
        .WithServiceBase()
)

In few articles I read that Windsor can wire a decorator chain automatically, if all components are registered in a valid order. But in my case Windsor just ignores my CachingQueryHandler registration when I trying to resolve any IQueryable<,>. In container's private field named Potentially Misconfigured Components I found this warning:

Some dependencies of this component could not be statically resolved. IGSystems.Common.CQRS.CachingQueryHandler'2 is waiting for the following dependencies: - Service 'IQueryHandler'2' which points back to the component itself. A dependency cannot be satisfied by the component itself, did you forget to register other components for this service?

回答1:

Well if you want your caching query handler to decorate your real implementation, you should reorder your registrations.

container.Register(
    Classes
        .FromAssemblyContaining<GetUserCourseStatesHandler>()
        .BasedOn(typeof(IQueryHandler<,>))
        .WithServiceBase(),
Component
        .For(typeof(IQueryHandler<,>))
        .ImplementedBy(typeof(CachingQueryHandler<,>))
)