我试图在我的命令处理程序上拦截对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);
}
}
}
答案 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>())
);
}