Castle windsor intercepter

2019-02-27 07:46发布

I am trying to intercept calls to the Handle method on my command handlers. this process works fine when I explicitly register each command handler, the problem is that my generic registration of the command handlers and the interceptor is not correct.

exception:

An exception of type 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' occurred in Castle.Windsor.dll but was not handled in user code

Additional information: ComponentActivator: could not proxy TempSearch.Command.Data.CommandHandlers.AddTempsJobCommandHandler

It looks like it cannot find the intercepter as it says that some components are misconfigured:

"Some dependencies of this component could not be statically resolved.\r\n'TempSearch.Command.Data.CommandHandlers.AddTempsCandidateAvailabilityCommandHandler' is waiting for the following dependencies:\r\n- Component 'TempSearch.Ioc.ExceptionHandlingIntercepter' (via override) which was not found. Did you forget to register it or misspelled the name? If the component is registered and override is via type make sure it doesn't have non-default name assigned explicitly or override the dependency via name.\r\n"

The interface:

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

an example Command Handler:

public class AddTempsCandidateAvailabilityCommandHandler 
    : ICommandHandler<TempsCandidateAvailability>
{
    private readonly IDbConnection connection;

    public AddTempsCandidateAvailabilityCommandHandler(
        IDbConnection connection)
    {
        this.connection = connection;
    }

    public void Handle(TempsCandidateAvailability command)
    {
        // ...
    }
}

the registeration:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
        Component.For<IDbConnection>()
            .UsingFactoryMethod(() => ConnectionHelper.GetOpenDbConnection(
                Connection.DatabaseName.ReedOnline))
            .LifestylePerWebRequest());

    container.Register(
        Classes
            .FromAssemblyContaining<EcruiterCommands>()
            .Where(t => t.Name.EndsWith("Commands"))
            .WithService
            .AllInterfaces().LifestylePerWebRequest());

    container.Register(
        Classes
            .FromAssemblyContaining<EcruiterCommands>()
            .Where(t => t.Name.EndsWith("CommandHandler"))
            .WithService.AllInterfaces()
            .LifestylePerWebRequest()
            .Configure(c => c.Interceptors<ExceptionHandlingIntercepter>()
                .LifestyleTransient()));
}

the intercepter:

[Transient]
public class ExceptionHandlingIntercepter : IInterceptor
{
    private static readonly MethodInfo Execute = 
        typeof(ICommandHandler<>).GetMethod("Handle");

    private readonly IKernel kernel;

    public ExceptionHandlingIntercepter(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method != Execute)
        {
            invocation.Proceed();
            return;
        }

        try
        {
            invocation.Proceed();
        }
        finally
        {
            kernel.ReleaseComponent(invocation.Proxy);
        }
    }
}

2条回答
放荡不羁爱自由
2楼-- · 2019-02-27 08:05

You must register the interceptor itself in order to let Castle resolve it when initializing your command handlers. Add the following to your registration:

container.Register(
    Component.For<ExceptionHandlingIntercepter>(); // should be enough

I like naming my interceptors to register them by name (don't know why, since your way should work fine)

查看更多
可以哭但决不认输i
3楼-- · 2019-02-27 08:18

I fixed this using this code:

public void Install(IWindsorContainer container, IConfigurationStore store)
        {    
            container.Register(
                Component.For<IInterceptor>()
                    .ImplementedBy<ExceptionHandlingIntercepter>().LifestyleTransient(),
                Classes
                    .FromAssemblyContaining<EcruiterCommands>()
                    .Where(t => t.Name.EndsWith("CommandHandler"))
                    .WithServiceAllInterfaces()
                    .LifestylePerWebRequest().Configure(c => c.Interceptors<ExceptionHandlingIntercepter>())
                );
        }
查看更多
登录 后发表回答