城堡温莎拦截器

Castle windsor intercepter

我正在尝试拦截对我的命令处理程序上的 Handle 方法的调用。 当我显式注册每个命令处理程序时,这个过程工作正常,问题是我对命令处理程序和拦截器的一般注册不正确。

异常:

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

它看起来像它说的那样找不到拦截器 某些组件配置错误:

"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"

接口:

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

命令处理程序示例:

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

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

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

报名人数:

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()));
}

拦截器:

[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);
        }
    }
}

您必须注册拦截器本身,以便让 Castle 在初始化您的命令处理程序时解析它。将以下内容添加到您的注册中:

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

我喜欢命名我的拦截器以按名称注册它们(不知道为什么,因为你的方式应该可以正常工作)

我用这段代码解决了这个问题:

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>())
                );
        }