Base solution for your next web application
Open Closed

Castel windsor interception on instancied component #7499


User avatar
0
willignicolas created

Hi ,

I'm trying to implement interceptor on an instantiated class with castle windsor, 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 :

<br>

public interface ITransferProtocolFactory { ITransferProtocol GetTransferProtocol(string transferProtocolName); }

Registration of the factory:

<br>

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 :

<br>

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:

<br>

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


3 Answer(s)
  • User Avatar
    0
    willignicolas created

    And on the same subject, a component that is a instancied object seems to cannot have dependency injection in his class.

    Is it correct?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @willignicolas

    Have you solved this problem. I haven't tried something like this before.

    And on the same subject, a component that is a instancied object seems to cannot have dependency injection in his class.

    This sounds correct. You can use IocManager.Instance to resolve dependencies manually and release them manually after you use them.

  • User Avatar
    0
    willignicolas created

    Hi,

    Thanks for your answer.

    No sorry I have not resolved the two issues. Interception of an instance and injection in the instance.

    Yes for the injection in the class of the instance component the manual resolve with iocmanager will certainly work thanks.

    I have injected my instance component to use interceptor on the first place so I'm still stuck with that for the moment. I have posted the question on stackoverflow (https://stackoverflow.com/questions/57522815/intercept-a-class-instance-with-castle-windsor) and on the support mailling list of castle windsor with no answer for now.

    Nicolas.