-
Notifications
You must be signed in to change notification settings - Fork 27
Description
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?