unitycontainer / interception

Unity.Interception package
Apache License 2.0
22 stars 17 forks source link

Interception doesn't work for instance added with RegisterInstance #35

Open vcpp opened 4 years ago

vcpp commented 4 years ago
  1. Prepare some class and its interface.
  2. Manually create an instance of that class and register it using RegisterInstance method.
  3. Set transparent proxy interceptor for the interface.
  4. Resolve an object by the interface.

Current: container returns original instance, all method calls go directly to that instance. Expected: container returns a proxy wrapper, method calls can be handled by the interceptor.

Broken versions: 5.x (tried 5.9.0 and latest stable 5.11.1). Working versions: 4.0.1 and older.

There is no problem with RegisterType method, unity returns a proxy wrapper as expected in a such scenario. The issue affects only RegisterInstance-way. Both default and named instances are being returned unwrapped.

Below is a unit test to demonstrate the issue, it works well with Unity versions up to 4.0.1 and fails with 5.x:

[TestFixture]
public class InterceptionTests
{
    [Test]
    public void RegisteredInstanceIntercepting_ReturnsProxy()
    {
        var container = new UnityContainer();
        container.AddNewExtension<Interception>();

        var instance = new SomeService();

        container
            .RegisterInstance<ISomeService>(instance)
            .Configure<Interception>()
            .SetInterceptorFor<ISomeService>(new TransparentProxyInterceptor())
            .AddPolicy("SomePolicy")
            .AddMatchingRule(new TypeMatchingRule(typeof(ISomeService)))
            .AddCallHandler(new SomeCallHandler());

        var wrapper = container.Resolve<ISomeService>();

        Assert.IsTrue(RemotingServices.IsTransparentProxy(wrapper), "Wrapper is not a proxy");
        Assert.AreNotSame(instance, wrapper);
    }

    private interface ISomeService
    {
        void Foo();
    }

    private sealed class SomeService : ISomeService
    {
        public void Foo() => throw new NotImplementedException();
    }

    private sealed class SomeCallHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) => throw new NotImplementedException();
        public int Order { get; set; }
    }
}

Is it enough for you or should I attach a zip with the whole project? Am I missing some breaking change with interceptors between 4.x and 5.x? Is there some workaround?

uniezuka commented 4 years ago

I have the same issue. Does anyone has already solve this?