volosoft / castle-windsor-ms-adapter

Castle Windsor ASP.NET Core / Microsoft.Extensions.DependencyInjection Adapter
https://www.nuget.org/packages/Castle.Windsor.MsDependencyInjection
MIT License
85 stars 29 forks source link

Potential Memory Leak when using IInterceptor #6

Closed nhart12 closed 7 years ago

nhart12 commented 7 years ago

I added the following test to your WindsorSpecificationTests and noticed it doesn't call Dispose on objects that get intercepted.

        public class MyTestInterceptor : IInterceptor
        {
            public void Intercept(IInvocation invocation) {
                invocation.Proceed();
            }
        }
        [Fact]
        public void ResolvingAndDisposingWithIInterceptorShouldWork ()
        {
            var collection = new ServiceCollection();
            collection.AddScoped<MyTestClass1>();
            var serviceProvider = CreateServiceProvider(collection);
            var windsorContainer = serviceProvider.GetService<IWindsorContainer>();
            windsorContainer.Register(Component.For<MyTestInterceptor>().LifestyleTransient());
            windsorContainer.Register(Component.For<MyTestClass2>().LifestyleTransient());
            windsorContainer.Register(Component.For<MyTestClass3>().LifestyleTransient()
                .Interceptors(InterceptorReference.ForType<MyTestInterceptor>()).Anywhere);
            using (var scope = serviceProvider.CreateScope())
            {
                var test1 = scope.ServiceProvider.GetService<MyTestClass1>();
                _disposeCounter.Get<MyTestClass1>().ShouldBe(0);
                _disposeCounter.Get<MyTestClass2>().ShouldBe(0);
                _disposeCounter.Get<MyTestClass3>().ShouldBe(0);
            }
            _disposeCounter.Get<MyTestClass1>().ShouldBe(1);
            _disposeCounter.Get<MyTestClass2>().ShouldBe(1);
            _disposeCounter.Get<MyTestClass3>().ShouldBe(1);
        }
hikalkan commented 7 years ago

Hi,

This code does not pass the test, but actually Windsor is calling Dispose method of MyTestClass3. You can add a breakpoint to it's Dispose method and see.

So, why unit test fails? Simple.. Because unit test is not designed to handle proxied types. When you add interceptor, Windsor replaces MyTestClass3 with MyTestClass3Proxy and disposes it. But unit test checks if an object of type MyTestClass3 disposed.

image

So, there is no problem on that.

hikalkan commented 7 years ago

see my commit: https://github.com/volosoft/castle-windsor-ms-adapter/commit/3b24c1ae482741d6de2f641a9578726b81827213