diff --git a/src/LightInject/LightInject.cs b/src/LightInject/LightInject.cs index 28651df9..ab9d9445 100644 --- a/src/LightInject/LightInject.cs +++ b/src/LightInject/LightInject.cs @@ -4729,6 +4729,147 @@ public IScopeManager GetScopeManager(IServiceFactory serviceFactory) protected abstract IScopeManager CreateScopeManager(IServiceFactory serviceFactory); } + /// + /// A scope manager that is none-static and pass the scope through 'state' + /// + internal class NonStaticServiceScopeRootManager : IScopeManager + { + public NonStaticServiceScopeRootManager(IServiceFactory serviceFactory) + { + ServiceFactory = serviceFactory; + } + + public IServiceFactory ServiceFactory { get; } + + [ThreadStatic] + private static Scope _scope; + public Scope CurrentScope { get => _scope; set => _scope = value; } + + + public Scope BeginScope() + { + var childScopeManager = new NonStaticServiceScopeManager(this, ServiceFactory); + var childScope = new Scope(childScopeManager, CurrentScope); + childScopeManager.CurrentScope = childScope; + return childScope; + } + + public void EndScope(Scope scope) + { + } + + } + + /// + /// A scope manager that is none-static and pass the scope through 'state' + /// + internal class NonStaticServiceFactoryWrapper : IServiceFactory + { + private readonly IServiceFactory _serviceFactoryImplementation; + private readonly IScopeManager _scopeManager; + + public NonStaticServiceFactoryWrapper(IServiceFactory serviceFactoryImplementation, IScopeManager scopeManager) + { + _serviceFactoryImplementation = serviceFactoryImplementation; + _scopeManager = scopeManager; + } + + public Scope BeginScope() + { + return _scopeManager.BeginScope(); + } + + public object GetInstance(Type serviceType) + { + return _serviceFactoryImplementation.GetInstance(serviceType); + } + + public object GetInstance(Type serviceType, object[] arguments) + { + return _serviceFactoryImplementation.GetInstance(serviceType, arguments); + } + + public object GetInstance(Type serviceType, string serviceName, object[] arguments) + { + return _serviceFactoryImplementation.GetInstance(serviceType, serviceName, arguments); + } + + public object GetInstance(Type serviceType, string serviceName) + { + return _serviceFactoryImplementation.GetInstance(serviceType, serviceName); + } + + public object TryGetInstance(Type serviceType) + { + return _serviceFactoryImplementation.TryGetInstance(serviceType); + } + + public object TryGetInstance(Type serviceType, string serviceName) + { + return _serviceFactoryImplementation.TryGetInstance(serviceType, serviceName); + } + + public IEnumerable GetAllInstances(Type serviceType) + { + return _serviceFactoryImplementation.GetAllInstances(serviceType); + } + + public object Create(Type serviceType) + { + return _serviceFactoryImplementation.Create(serviceType); + } + } + + /// + /// A scope manager that is none-static and pass the scope through 'state' + /// + internal class NonStaticServiceScopeManager : IScopeManager + { + private readonly NonStaticServiceScopeRootManager _root; + public NonStaticServiceScopeManager(NonStaticServiceScopeRootManager root, IServiceFactory serviceFactory) + { + _root = root; + ServiceFactory = new NonStaticServiceFactoryWrapper(root.ServiceFactory, this); + } + + public IServiceFactory ServiceFactory { get; } + + private Scope _currentScope; + public virtual Scope CurrentScope + { + get => _root.CurrentScope; + set => _root.CurrentScope = value; + } + + public virtual Scope BeginScope() + { + var childScopeManager = new NonStaticServiceScopeManager(_root, ServiceFactory); + var childScope = new Scope(childScopeManager, _currentScope); + childScopeManager._currentScope = childScope; + _currentScope.ChildScope = childScope; + return childScope; + } + + public void EndScope(Scope scope) + { + if (ReferenceEquals(_currentScope, scope)) + scope.ParentScope.ChildScope = null; + } + + } + + /// + /// A scope manager that is none-static and pass the scope through 'state' + /// + public class NonStaticServiceScopeManagerProvider : IScopeManagerProvider + { + public IScopeManager GetScopeManager(IServiceFactory serviceFactory) + { + var ret = new NonStaticServiceScopeRootManager(serviceFactory); + return ret; + } + } + /// /// A that provides a per thread. ///