Intercept a class instance with Castle Windsor

91 views
Skip to first unread message

Nicolas Willig

unread,
Aug 17, 2019, 9:00:14 AM8/17/19
to Castle Project Users
Hi castle windsor lovers,

I'm trying to implement interceptor on an instantiated class, but no methods are intercepted in this case. All works fine with normally registered components, Castle Windsor intercepts all the methods of my component.

I know that by design Castle Windsor cannot intercept a registered instantiated class, but I was saw this post and tried to implement it with no luck: https://stackoverflow.com/questions/12162769/castle-windsor-cannot-intercept-component-registered-for-a-class-instance

This is my current implementation :

My Factory Interface :

public interface ITransferProtocolFactory
{
ITransferProtocol GetTransferProtocol(string transferProtocolName);
}
Registration of the factory:

IocManager.IocContainer.AddFacility<TypedFactoryFacility>();
IocManager.IocContainer.Register(Component.For<ITransferProtocolFactory>().AsFactory(new NamedTypeFactory()));
IocManager.IocContainer.Register(Component.For<NamedTypeFactory, ITypedFactoryComponentSelector>());
Override of the GetComponentName method :

public class NamedTypeFactory : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
string componentName = null;
if (arguments != null && arguments.Length > 0)
{
componentName = arguments[0] as string;
}
if (string.IsNullOrEmpty(componentName))
componentName = base.GetComponentName(method, arguments);
return componentName;
}
}
Registering my interceptor :

public static class InterceptorsRegistrar
{
public static void Initialize(IKernel kernel)
{
kernel.ComponentRegistered += Kernel_ComponentRegistered;
}

private static void Kernel_ComponentRegistered(string key, IHandler handler)
{
if (typeof(ITransferProtocol).IsAssignableFrom(handler.ComponentModel.Implementation) &&
!typeof(IProxyTransferUserAction).IsAssignableFrom(handler.ComponentModel.Implementation))
{
handler.ComponentModel.Interceptors.Add
(new InterceptorReference(typeof(TransferUserActionInterceptor)));
}
}
}

InterceptorsRegistrar.Initialize(IocManager.IocContainer.Kernel);
Creation of instance and registration :

public void CreateAndInjectMachineProtocol(MachineForAgentDto machine)
{
var machineProtocol = (ITransferProtocol)Activator.CreateInstance(Type.GetType("Agent.Protocols." + Enum.GetName(typeof(eCommunicationType), machine.CommunicationType)));

_iocManager.IocContainer.Register(Component.For<ITransferProtocol>().Instance(machineProtocol).Named(nameof(ITransferProtocol) + machine.Id.ToString()).LifestyleSingleton());
}
The Interceptor :

public class TransferUserActionInterceptor : IInterceptor
{
private readonly IMachineManager _machineManager;

public TransferUserActionInterceptor(IMachineManager machineManager)
{
_machineManager = machineManager;
}

public void Intercept(IInvocation invocation)
{
invocation.Proceed();
}
}
And finally the resolver of the component through the factory:

private ITransferProtocol GetMachineProtocol(long machineId)
{
return _transferProtocolFactory.GetTransferProtocol(nameof(ITransferProtocol) + machineId.ToString());
}
The Interception is not working in this case because of the design limitation of Castle Windsor.

I have trid to implement this solution https://stackoverflow.com/questions/12162769/castle-windsor-cannot-intercept-component-registered-for-a-class-instance but the interception continue not to working (maybe I have implemented it wrong).

So here are my 2 questions :

How can I implement the stackoverflow post solution on top of my current code to let methods of the ITransferProtocol injected instance be intercepted?

Do you have another solution that the stackoverflow post suggest?

Thanks for your help.

Nicolas
Reply all
Reply to author
Forward
0 new messages