77 */
88
99using System ;
10+ using System . Collections . Concurrent ;
1011using System . Collections . Generic ;
1112using System . Linq ;
13+ using System . Threading ;
1214
1315namespace Core . Inject
1416{
1517 /// <summary>
1618 /// A simple dependency injection container that handles the registration and resolution of services.
1719 /// Supports singleton, transient, scoped, and instance-based registrations.
1820 /// </summary>
19- public sealed class CoreInjector
21+ public sealed class CoreInjector : IDisposable
2022 {
2123 /// <summary>
2224 /// Stores the registered service factories, indexed by service type.
2325 /// </summary>
2426 private readonly Dictionary < Type , Func < object > > _registrations = new ( ) ;
2527
28+ /// <summary>
29+ /// The singleton instances
30+ /// </summary>
31+ private readonly ConcurrentDictionary < Type , object > _singletonInstances = new ( ) ;
32+
2633 /// <summary>
2734 /// The current scope for managing scoped dependencies.
2835 /// </summary>
29- private SimpleScope _currentScope ;
36+ private readonly AsyncLocal < SimpleScope ? > _currentScope = new ( ) ;
3037
3138 /// <summary>
3239 /// Registers a singleton service with a specific implementation type.
@@ -35,16 +42,10 @@ public sealed class CoreInjector
3542 /// <typeparam name="TService">The service type.</typeparam>
3643 /// <typeparam name="TImplementation">The implementation type for the service.</typeparam>
3744 /// <exception cref="InvalidOperationException">Thrown if the service is already registered.</exception>
38- public void RegisterSingleton < TService , TImplementation > ( ) where TImplementation : TService , new ( )
45+ public void RegisterSingleton < TService , TImplementation > ( ) where TImplementation : TService
3946 {
40- if ( _registrations . ContainsKey ( typeof ( TService ) ) )
41- {
42- throw new InvalidOperationException ( string . Format ( CoreInjectResource . ErrorServiceRegisteredSingleTon ,
43- typeof ( TService ) . Name ) ) ;
44- }
45-
46- TImplementation instance = new ( ) ;
47- _registrations [ typeof ( TService ) ] = ( ) => instance ; // Always return the same instance
47+ _registrations [ typeof ( TService ) ] = ( ) =>
48+ _singletonInstances . GetOrAdd ( typeof ( TService ) , _ => CreateInstance ( typeof ( TImplementation ) ) ) ;
4849 }
4950
5051 /// <summary>
@@ -109,12 +110,12 @@ public void RegisterInstance<TService>(TService instance)
109110 {
110111 _registrations [ typeof ( TService ) ] = ( ) =>
111112 {
112- if ( _currentScope == null )
113+ if ( _currentScope . Value == null )
113114 {
114115 throw new InvalidOperationException ( CoreInjectResource . ErrorNoActiveScope ) ;
115116 }
116117
117- return _currentScope . Resolve < TService > ( ( ) => new TImplementation ( ) ) ;
118+ return _currentScope . Value . Resolve < TService > ( ( ) => new TImplementation ( ) ) ;
118119 } ;
119120 }
120121
@@ -143,9 +144,9 @@ public void RegisterTransient(Type serviceType, Type implementationType)
143144 /// <returns>The resolved service instance.</returns>
144145 public TService Resolve < TService > ( )
145146 {
146- if ( _currentScope != null && _registrations . ContainsKey ( typeof ( TService ) ) )
147+ if ( _currentScope . Value != null && _registrations . ContainsKey ( typeof ( TService ) ) )
147148 {
148- return _currentScope . Resolve < TService > ( ( ) => ( TService ) _registrations [ typeof ( TService ) ] ( ) ) ;
149+ return _currentScope . Value . Resolve < TService > ( ( ) => ( TService ) _registrations [ typeof ( TService ) ] ( ) ) ;
149150 }
150151
151152 return ( TService ) Resolve ( typeof ( TService ) ) ;
@@ -157,7 +158,7 @@ public TService Resolve<TService>()
157158 /// </summary>
158159 public void BeginScope ( )
159160 {
160- _currentScope = new SimpleScope ( ) ;
161+ _currentScope . Value = new SimpleScope ( ) ;
161162 }
162163
163164 /// <summary>
@@ -166,10 +167,22 @@ public void BeginScope()
166167 /// </summary>
167168 public void EndScope ( )
168169 {
169- _currentScope ? . Dispose ( ) ;
170- _currentScope = null ;
170+ _currentScope . Value ? . Dispose ( ) ;
171+ _currentScope . Value = null ;
171172 }
172173
174+ /// <summary>
175+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
176+ /// </summary>
177+ public void Dispose ( )
178+ {
179+ // Only dispose things we actually created!
180+ foreach ( var instance in _singletonInstances . Values )
181+ {
182+ ( instance as IDisposable ) ? . Dispose ( ) ;
183+ }
184+ _singletonInstances . Clear ( ) ;
185+ }
173186
174187 /// <summary>
175188 /// Resolves a service by its type.
0 commit comments