From 7437a7c69cfc29a9cc15c435db3ec61955242142 Mon Sep 17 00:00:00 2001 From: Gian Maria Ricci Date: Thu, 15 Feb 2024 13:19:07 +0100 Subject: [PATCH] Added logic to support multiple container in .NET 8 DI Needed to modify basic Castle.Winsor library to support the ability from IHandler interface to get the current kernel associated with the handler. This is needed to find the correct root scope associated with that kernel instance. --- buildscripts/common.props | 4 +- .../CustomAssumptionTests.cs | 17 ++- .../ResolveFromThreadpoolUnsafe.cs | 27 +++-- ...edDependencyInjectionSpecificationTests.cs | 108 +++--------------- ...viceProviderCustomWindsorContainerTests.cs | 31 ++++- .../WindsorScopedServiceProviderTests.cs | 31 ++++- ...dsor.Extensions.DependencyInjection.csproj | 6 +- .../ExtensionContainerRootScopeAccessor.cs | 13 +-- .../Scope/ExtensionContainerScopeBase.cs | 5 - .../WindsorServiceProviderFactoryBase.cs | 48 ++++---- .../Castle.Windsor.Extensions.Hosting.csproj | 2 +- .../DefaultComponentActivator.cs | 5 +- .../MicroKernel/DefaultKernel.cs | 7 +- .../MicroKernel/Handlers/AbstractHandler.cs | 5 + .../Handlers/ParentHandlerWrapper.cs | 5 + src/Castle.Windsor/MicroKernel/IHandler.cs | 6 + 16 files changed, 155 insertions(+), 165 deletions(-) diff --git a/buildscripts/common.props b/buildscripts/common.props index 266e4e4ff4..6791e6c986 100644 --- a/buildscripts/common.props +++ b/buildscripts/common.props @@ -4,7 +4,7 @@ $(NoWarn);CS1591;NU5048 git https://github.com/castleproject/Windsor - 6.0.0 + 0.0.0 $(APPVEYOR_BUILD_VERSION) $(BuildVersion.Split('.')[0]) $(BuildVersion.Split('-')[0]) @@ -18,7 +18,7 @@ Castle Windsor $(BuildVersionNoSuffix) $(BuildVersion) - 6.0.0.0 + $(BuildVersionMajor).0.0 Castle Windsor is best of breed, mature Inversion of Control container available for .NET Castle Project Contributors http://www.castleproject.org/projects/windsor/ diff --git a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/CustomAssumptionTests.cs b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/CustomAssumptionTests.cs index 4bba519bf3..ac83c0f0ab 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/CustomAssumptionTests.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/CustomAssumptionTests.cs @@ -282,6 +282,7 @@ protected override IServiceProvider BuildServiceProvider(IServiceCollection serv public class CastleWindsorCustomAssumptionTests : CustomAssumptionTests { + private WindsorServiceProviderFactory _factory; private IWindsorContainer _container; protected override IServiceCollection GetServiceCollection() @@ -291,9 +292,9 @@ protected override IServiceCollection GetServiceCollection() protected override IServiceProvider BuildServiceProvider(IServiceCollection serviceCollection) { - var factory = new WindsorServiceProviderFactory(); - _container = factory.CreateBuilder(serviceCollection); - return factory.CreateServiceProvider(_container); + _factory = new WindsorServiceProviderFactory(); + _container = _factory.CreateBuilder(serviceCollection); + return _factory.CreateServiceProvider(_container); } [Fact] @@ -351,6 +352,16 @@ public void TryToResolveScopedInOtherThread() Assert.True(task.Result); } + + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _factory.Dispose(); + } + } } internal class TestService : ITestService diff --git a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/ResolveFromThreadpoolUnsafe.cs b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/ResolveFromThreadpoolUnsafe.cs index 68844e4bc3..1f91093574 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/ResolveFromThreadpoolUnsafe.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/ResolveFromThreadpoolUnsafe.cs @@ -30,11 +30,11 @@ public ResolveFromThreadpoolUnsafe_NetStatic() : base(false) /// NetStatic lifestyle. /// [Fact] - public async Task Cannot_Resolve_LifestyleNetStatic_From_WindsorContainer_NoRootScopeAvailable() + public async Task Can_Resolve_LifestyleNetStatic_From_WindsorContainer_NoRootScopeAvailable() { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -68,14 +68,13 @@ public async Task Cannot_Resolve_LifestyleNetStatic_From_WindsorContainer_NoRoot { var task = tcs.Task; IUserService result = await task; - // The test succeeds if we use standard Castle Windsor Singleton lifestyle instead of the custom NetStatic lifestyle. + //with the fix we can now use correctly a fallback for the root scope so we can access root scope even + //if we are outside of scope Assert.NotNull(result); }); // This test will fail if we use NetStatic lifestyle - Assert.NotNull(ex); - Assert.IsType(ex); - Assert.Equal("No root scope available.", ex.Message); + Assert.Null(ex); (sp as IDisposable)?.Dispose(); container.Dispose(); @@ -315,7 +314,7 @@ public async Task Cannot_Resolve_LifestyleScoped_From_ServiceProvider() { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -373,7 +372,7 @@ public async Task Cannot_Resolve_LifestyleScoped_From_WindsorContainer() { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -432,7 +431,7 @@ public async Task Can_Resolve_LifestyleScopedToNetServiceScope_From_ServiceProvi { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -475,7 +474,7 @@ public async Task Cannot_Resolve_LifestyleScopedToNetServiceScope_From_WindsorCo { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -540,7 +539,7 @@ public async Task Can_Resolve_LifestyleTransient_From_ServiceProvider() { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -583,7 +582,7 @@ public async Task Can_Resolve_LifestyleTransient_From_WindsorContainer() { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -631,7 +630,7 @@ public async Task Can_Resolve_LifestyleNetTransient_From_ServiceProvider_MemoryL { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( @@ -674,7 +673,7 @@ public async Task Cannot_Resolve_LifestyleNetTransient_From_WindsorContainer_NoS { var serviceProvider = new ServiceCollection(); var container = new WindsorContainer(); - var f = new WindsorServiceProviderFactory(container); + using var f = new WindsorServiceProviderFactory(container); f.CreateBuilder(serviceProvider); container.Register( diff --git a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorKeyedDependencyInjectionSpecificationTests.cs b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorKeyedDependencyInjectionSpecificationTests.cs index 88da1a83fd..6fc401577f 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorKeyedDependencyInjectionSpecificationTests.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorKeyedDependencyInjectionSpecificationTests.cs @@ -6,119 +6,43 @@ namespace Castle.Windsor.Extensions.DependencyInjection.Tests { - public class WindsorKeyedDependencyInjectionSpecificationTests : KeyedDependencyInjectionSpecificationTests + public class WindsorKeyedDependencyInjectionSpecificationTests : KeyedDependencyInjectionSpecificationTests, IDisposable { + private bool _disposedValue; + private WindsorServiceProviderFactory _factory; + protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) { if (collection is TestServiceCollection) { - var factory = new WindsorServiceProviderFactory(); - var container = factory.CreateBuilder(collection); - return factory.CreateServiceProvider(container); + _factory = new WindsorServiceProviderFactory(); + var container = _factory.CreateBuilder(collection); + return _factory.CreateServiceProvider(container); } return collection.BuildServiceProvider(); } - //[Fact] - //public void ResolveKeyedServiceSingletonInstanceWithAnyKey2() - //{ - // var serviceCollection = new ServiceCollection(); - // serviceCollection.AddKeyedSingleton(KeyedService.AnyKey); - - // var provider = CreateServiceProvider(serviceCollection); - - // Assert.Null(provider.GetService()); - - // var serviceKey1 = "some-key"; - // var svc1 = provider.GetKeyedService(serviceKey1); - // Assert.NotNull(svc1); - // Assert.Equal(serviceKey1, svc1.ToString()); - - // var serviceKey2 = "some-other-key"; - // var svc2 = provider.GetKeyedService(serviceKey2); - // Assert.NotNull(svc2); - // Assert.Equal(serviceKey2, svc2.ToString()); - //} - - internal interface IService { } - - internal class Service : IService - { - private readonly string _id; - - public Service() => _id = Guid.NewGuid().ToString(); - - public Service([ServiceKey] string id) => _id = id; - - public override string? ToString() => _id; - } - - internal class OtherService + protected virtual void Dispose(bool disposing) { - public OtherService( - [FromKeyedServices("service1")] IService service1, - [FromKeyedServices("service2")] IService service2) + if (!_disposedValue) { - Service1 = service1; - Service2 = service2; - } - - public IService Service1 { get; } - - public IService Service2 { get; } - } - - public class FakeService : IFakeEveryService, IDisposable - { - public PocoClass Value { get; set; } - - public bool Disposed { get; private set; } - - public void Dispose() - { - if (Disposed) + if (disposing) { - throw new ObjectDisposedException(nameof(FakeService)); + _factory?.Dispose(); } - Disposed = true; + _disposedValue = true; } } - public interface IFakeEveryService : - IFakeService, - IFakeMultipleService, - IFakeScopedService - { - } - - public interface IFakeMultipleService : IFakeService - { - } - - public interface IFakeScopedService : IFakeService - { - } - - public interface IFakeService - { - } - - public class PocoClass + public void Dispose() { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); } } - - //public class WindsorKeyedDependencyInjectionSpecificationExplicitContainerTests : KeyedDependencyInjectionSpecificationTests - //{ - // protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) - // { - // var factory = new WindsorServiceProviderFactory(new WindsorContainer()); - // var container = factory.CreateBuilder(collection); - // return factory.CreateServiceProvider(container); - // } - //} } #endif diff --git a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderCustomWindsorContainerTests.cs b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderCustomWindsorContainerTests.cs index 112ca051ac..54f909b975 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderCustomWindsorContainerTests.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderCustomWindsorContainerTests.cs @@ -21,13 +21,36 @@ namespace Castle.Windsor.Extensions.DependencyInjection.Tests using Microsoft.Extensions.DependencyInjection.Specification.Fakes; using Xunit; - public class WindsorScopedServiceProviderCustomWindsorContainerTests : SkippableDependencyInjectionSpecificationTests + public class WindsorScopedServiceProviderCustomWindsorContainerTests : SkippableDependencyInjectionSpecificationTests, IDisposable { + private bool _disposedValue; + private WindsorServiceProviderFactory _factory; + protected override IServiceProvider CreateServiceProviderImpl(IServiceCollection serviceCollection) { - var factory = new WindsorServiceProviderFactory(new WindsorContainer()); - var container = factory.CreateBuilder(serviceCollection); - return factory.CreateServiceProvider(container); + _factory = new WindsorServiceProviderFactory(new WindsorContainer()); + var container = _factory.CreateBuilder(serviceCollection); + return _factory.CreateServiceProvider(container); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _factory?.Dispose(); + } + + _disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); } #if NET6_0_OR_GREATER diff --git a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderTests.cs b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderTests.cs index c335dd163b..c567ba7c1f 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderTests.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection.Tests/WindsorScopedServiceProviderTests.cs @@ -19,13 +19,36 @@ namespace Castle.Windsor.Extensions.DependencyInjection.Tests using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Specification; - public class WindsorScopedServiceProviderTests : SkippableDependencyInjectionSpecificationTests + public class WindsorScopedServiceProviderTests : SkippableDependencyInjectionSpecificationTests, IDisposable { + private bool _disposedValue; + private WindsorServiceProviderFactory _factory; + protected override IServiceProvider CreateServiceProviderImpl(IServiceCollection serviceCollection) { - var factory = new WindsorServiceProviderFactory(); - var container = factory.CreateBuilder(serviceCollection); - return factory.CreateServiceProvider(container); + _factory = new WindsorServiceProviderFactory(); + var container = _factory.CreateBuilder(serviceCollection); + return _factory.CreateServiceProvider(container); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _factory?.Dispose(); + } + + _disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); } } } diff --git a/src/Castle.Windsor.Extensions.DependencyInjection/Castle.Windsor.Extensions.DependencyInjection.csproj b/src/Castle.Windsor.Extensions.DependencyInjection/Castle.Windsor.Extensions.DependencyInjection.csproj index f1012afd0a..9884c8b7a3 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection/Castle.Windsor.Extensions.DependencyInjection.csproj +++ b/src/Castle.Windsor.Extensions.DependencyInjection/Castle.Windsor.Extensions.DependencyInjection.csproj @@ -36,7 +36,7 @@ - - - + + + diff --git a/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerRootScopeAccessor.cs b/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerRootScopeAccessor.cs index e6ccdcff2c..88f4f3d383 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerRootScopeAccessor.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerRootScopeAccessor.cs @@ -14,10 +14,9 @@ namespace Castle.Windsor.Extensions.DependencyInjection.Scope { - using System; - using Castle.Core.Logging; using Castle.MicroKernel.Context; using Castle.MicroKernel.Lifestyle.Scoped; + using System; internal class ExtensionContainerRootScopeAccessor : IScopeAccessor { @@ -25,17 +24,11 @@ public ILifetimeScope GetScope(CreationContext context) { if (ExtensionContainerScopeCache.Current?.RootScope == null) { - //TODO: if we have a way from context to retrieve the instance of container/kernel we could use it to get - //a reference of the correct root scope with a call to WindsorServiceProviderFactoryBase.GetSingleRootScope - //but since in this version we cannot determine the container from this context. - - //In this version we have the limit to have only one container registered in the dependency injection chain of - //.NET core, so we call a different method that gives us the single root scope. - var scope = WindsorServiceProviderFactoryBase.GetSingleRootScope(); + var scope = WindsorServiceProviderFactoryBase.GetRootScopeForKernel(context.Handler.GetKernel()); if (scope == null) { - throw new InvalidOperationException($"{nameof(ExtensionContainerRootScopeAccessor)}: We are trying to access a ROOT scope null for requested type {context.RequestedType}"); + throw new InvalidOperationException($"{nameof(ExtensionContainerRootScopeAccessor)}: We are trying to access a ROOT scope null for requested type {context.RequestedType} current kernel is not associated with any root scope"); } return scope; diff --git a/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerScopeBase.cs b/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerScopeBase.cs index ac94760a48..c372ef5ecc 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerScopeBase.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection/Scope/ExtensionContainerScopeBase.cs @@ -25,14 +25,9 @@ internal abstract class ExtensionContainerScopeBase : ILifetimeScope public static readonly string TransientMarker = "Transient"; private readonly IScopeCache scopeCache; - private static long _counter; - - public long Counter { get; private set; } - protected ExtensionContainerScopeBase() { scopeCache = new ScopeCache(); - Counter = Interlocked.Increment(ref _counter); } internal virtual ExtensionContainerScopeBase RootScope { get; set; } diff --git a/src/Castle.Windsor.Extensions.DependencyInjection/WindsorServiceProviderFactoryBase.cs b/src/Castle.Windsor.Extensions.DependencyInjection/WindsorServiceProviderFactoryBase.cs index bba76fd149..e507916f39 100644 --- a/src/Castle.Windsor.Extensions.DependencyInjection/WindsorServiceProviderFactoryBase.cs +++ b/src/Castle.Windsor.Extensions.DependencyInjection/WindsorServiceProviderFactoryBase.cs @@ -21,39 +21,26 @@ namespace Castle.Windsor.Extensions.DependencyInjection using Castle.Windsor.Extensions.DependencyInjection.Scope; using Microsoft.Extensions.DependencyInjection; using System; + using System.Collections.Concurrent; using System.Collections.Generic; - using System.Linq; - public abstract class WindsorServiceProviderFactoryBase : IServiceProviderFactory + public abstract class WindsorServiceProviderFactoryBase : IServiceProviderFactory, IDisposable { - private static readonly Dictionary _factoryBaseMap = new(); + private static readonly ConcurrentDictionary _factoryBaseMap = new(); - internal static ExtensionContainerRootScope GetRootScopeForContainer(IWindsorContainer container) + internal static ExtensionContainerRootScope GetRootScopeForKernel(IKernel kernel) { - if (_factoryBaseMap.TryGetValue(container, out var factory)) + if (_factoryBaseMap.TryGetValue(kernel, out var factory)) { return factory.RootScope; } throw new NotSupportedException("We are trying to access scopt for a container that was not associated with any WindsorServiceProviderFactoryBase. This is not supported."); } - internal static ExtensionContainerRootScope GetSingleRootScope() - { - if (_factoryBaseMap.Count == 0) - { - throw new NotSupportedException("No root scope created, did you forget to create an instance of IServiceProviderFActory?"); - } - else if (_factoryBaseMap.Count > 1) - { - throw new NotSupportedException("Multiple root scopes created, this is not supported because we cannot determine which is the right root scope bounded to actual container."); - } - - return _factoryBaseMap.Values.Single().RootScope; - } - internal ExtensionContainerRootScope RootScope { get; private set; } protected IWindsorContainer rootContainer; + private bool _disposedValue; public virtual IWindsorContainer Container => rootContainer; @@ -82,7 +69,7 @@ protected virtual void SetRootContainer(IWindsorContainer container) { rootContainer = container; //Set the map associating this factoryh with the container. - _factoryBaseMap[rootContainer] = this; + _factoryBaseMap[rootContainer.Kernel] = this; #if NET8_0_OR_GREATER rootContainer.Kernel.Resolver.AddSubResolver(new KeyedServicesSubDependencyResolver(rootContainer)); #endif @@ -171,5 +158,26 @@ protected virtual void AddSubResolvers() rootContainer.Kernel.Resolver.AddSubResolver(new OptionsSubResolver(rootContainer.Kernel)); rootContainer.Kernel.Resolver.AddSubResolver(new LoggerDependencyResolver(rootContainer.Kernel)); } + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + //when this is disposed just remove the kernel from the map. + _factoryBaseMap.TryRemove(this.Container.Kernel, out var _); + } + + _disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } } diff --git a/src/Castle.Windsor.Extensions.Hosting/Castle.Windsor.Extensions.Hosting.csproj b/src/Castle.Windsor.Extensions.Hosting/Castle.Windsor.Extensions.Hosting.csproj index c830167ea1..1aa19662d8 100644 --- a/src/Castle.Windsor.Extensions.Hosting/Castle.Windsor.Extensions.Hosting.csproj +++ b/src/Castle.Windsor.Extensions.Hosting/Castle.Windsor.Extensions.Hosting.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs b/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs index 9f2f33c4df..089ee7a6e0 100644 --- a/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs +++ b/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs @@ -138,10 +138,7 @@ protected virtual object CreateInstance(CreationContext context, ConstructorCand protected object CreateInstanceCore(ConstructorCandidate constructor, object[] arguments, Type implType) { object instance; - if (Model.Implementation.FullName.Contains("SiloConnectionFactory")) - { - - } + try { #if FEATURE_REMOTING diff --git a/src/Castle.Windsor/MicroKernel/DefaultKernel.cs b/src/Castle.Windsor/MicroKernel/DefaultKernel.cs index 2c94c47d31..46f8c9bd4c 100644 --- a/src/Castle.Windsor/MicroKernel/DefaultKernel.cs +++ b/src/Castle.Windsor/MicroKernel/DefaultKernel.cs @@ -694,9 +694,10 @@ protected CreationContext CreateCreationContext(IHandler handler, Type requested return new CreationContext(handler, policy, requestedType, additionalArguments, ConversionSubSystem, parent); } - /// - /// It is the responsibility of the kernel to ensure that handler is only ever disposed once. - /// + /// + /// It is the responsibility of the kernel to ensure that handler is only ever disposed once. + /// + /// protected void DisposeHandler(IHandler handler) { var disposable = handler as IDisposable; diff --git a/src/Castle.Windsor/MicroKernel/Handlers/AbstractHandler.cs b/src/Castle.Windsor/MicroKernel/Handlers/AbstractHandler.cs index 819b98a641..15c1bf6efd 100644 --- a/src/Castle.Windsor/MicroKernel/Handlers/AbstractHandler.cs +++ b/src/Castle.Windsor/MicroKernel/Handlers/AbstractHandler.cs @@ -126,6 +126,11 @@ private bool HasCustomParameter(object key) return model.CustomDependencies.Contains(key); } + IKernel IHandler.GetKernel() + { + return kernel; + } + /// /// Saves the kernel instance, subscribes to event, creates the lifestyle manager instance and computes the handler state. /// diff --git a/src/Castle.Windsor/MicroKernel/Handlers/ParentHandlerWrapper.cs b/src/Castle.Windsor/MicroKernel/Handlers/ParentHandlerWrapper.cs index 935fe552a0..c20af37787 100644 --- a/src/Castle.Windsor/MicroKernel/Handlers/ParentHandlerWrapper.cs +++ b/src/Castle.Windsor/MicroKernel/Handlers/ParentHandlerWrapper.cs @@ -62,6 +62,11 @@ public void Dispose() Dispose(true); } + IKernel IHandler.GetKernel() + { + return parentHandler.GetKernel(); + } + public virtual void Init(IKernelInternal kernel) { } diff --git a/src/Castle.Windsor/MicroKernel/IHandler.cs b/src/Castle.Windsor/MicroKernel/IHandler.cs index 4590bd4806..8f603b549e 100644 --- a/src/Castle.Windsor/MicroKernel/IHandler.cs +++ b/src/Castle.Windsor/MicroKernel/IHandler.cs @@ -82,5 +82,11 @@ public interface IHandler : ISubDependencyResolver /// /// object TryResolve(CreationContext context); + + /// + /// Needed to support root scope for multiple container when integrating with .NET 8 + /// DI engine. + /// + IKernel GetKernel(); } } \ No newline at end of file