Skip to content

Unable to cast exception on Injection with Dynamic Proxy and Interface Inheritance #45

@spam1923

Description

@spam1923

I have ran into an issue when binding two interfaces to the same concrete class when there is an Interceptor on the singleton binding.
Without the Interceptor these tests will all pass because when InterfaceA or InterfaceB is injected it is injected as the concrete class type. However with the interceptors it puts Castle.Proxies.InterfaceAProxy Or Castle.Proxies.InterfaceBProxy purely dependent upon which Kernel.Get was called first. Since InterfaceA inherits from InterfaceB, when InterfaceA goes first it can cast as the proxy for InterfaceB. But it will not work the other way around.

I have taken the complexity out of the instance I ran into and put it into a very basic scenario below. To run this snippet create a UnitTest Project in VisualStudio and add the Ninject.Extensions.Interception.DynamicProxy NuGet Package v3.3.3.

    public class Interceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            //Interceptor Logic
        }
    }

    public interface InterfaceB
    {
        //Definition
    }
    public interface InterfaceA : InterfaceB
    {
        //Definition
    }
    public class Implementation : InterfaceA
    {
        //Logic
    }

    public class BusinessLogic_One
    {
        private readonly InterfaceA _interface;
        public BusinessLogic_One(InterfaceA input)
        {
            _interface = input;
        }
    }

    public class BusinessLogic_Two
    {
        private readonly InterfaceB _interface;
        public BusinessLogic_Two(InterfaceB input)
        {
            _interface = input;
        }
    }

    [TestClass]
    public class UnitTests
    {
        private IKernel _kernel;
        [TestInitialize]
        public void TestInit()
        {
            _kernel = new StandardKernel();

           //If the Intercept().With<Interceptor>() is commented out all tests will pass.
            _kernel.Bind<InterfaceA, InterfaceB>().To<Implementation>().InSingletonScope()
                .Intercept().With<Interceptor>();
            _kernel.Bind<BusinessLogic_One>().ToSelf().InSingletonScope();
            _kernel.Bind<BusinessLogic_Two>().ToSelf().InSingletonScope();
        }

         
        [TestMethod]//Test Passes
        public void Test_Calling_KernelGet_InterfaceAFirst()
        {
            var bl1 = _kernel.Get<BusinessLogic_One>();//InterfaceA
            var bl2 = _kernel.Get<BusinessLogic_Two>();//InterfaceB
        }

        [TestMethod]//Test Fails
        public void Test_Calling_KernelGet_InterfaceBFirst()
        {
            var bl2 = _kernel.Get<BusinessLogic_Two>();//InterfaceB
            var bl1 = _kernel.Get<BusinessLogic_One>();//InterfaceA
        }
    }

The Exception I get on the Failed test is:
Message: Test method UnitTests.Test_Calling_KernelGet_InterfaceBFirst threw exception:
System.InvalidCastException: Unable to cast object of type 'Castle.Proxies.InterfaceBProxy' to type 'InterfaceA'.

Would it be possible in the next version for this to be a Castle.Proxies.ImplementationProxy or something that both interfaces could inherit from?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions