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);
}
}
}
You must register the interceptor itself in order to let Castle resolve it when initializing your command handlers. Add the following to your registration:
I like naming my interceptors to register them by name (don't know why, since your way should work fine)
I fixed this using this code: