城堡温莎拦截器

时间:2015-04-14 14:11:45

标签: c# dependency-injection castle-windsor ioc-container interception

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

异常:

  

类型的例外   'Castle.MicroKernel.ComponentActivator.ComponentActivatorException'   发生在Castle.Windsor.dll但未在用户代码中处理

     

其他信息:ComponentActivator:无法代理   TempSearch.Command.Data.CommandHandlers.AddTempsJobCommandHandler

它似乎无法找到截取的内容 某些组件配置错误:

  

“此组件的某些依赖项不能是静态的   解决了。​​\ r \ n'TempSearch.Command.Data.CommandHandlers.AddTempsCandidateAvailabilityCommandHandler”   正在等待以下依赖项:\ r \ n-组件   'TempSearch.Ioc.ExceptionHandlingIntercepter'(通过覆盖)是   未找到。你忘了注册或拼错了名字吗?如果   组件已注册,覆盖是通过类型确保它   没有明确指定的非默认名称或覆盖   依赖名称。\ 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);
        }
    }
}

2 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:0)

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

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