@@ -21,7 +21,7 @@ internal class ServiceProvider : IServiceProvider, IDisposable
21
21
private readonly ServiceTable _table ;
22
22
23
23
private readonly Dictionary < IService , object > _resolvedServices = new Dictionary < IService , object > ( ) ;
24
- private readonly List < IDisposable > _disposables = new List < IDisposable > ( ) ;
24
+ private List < IDisposable > _transientDisposables ;
25
25
26
26
private static readonly Func < Type , ServiceProvider , Func < ServiceProvider , object > > _createServiceAccessor = CreateServiceAccessor ;
27
27
@@ -42,6 +42,9 @@ internal ServiceProvider(ServiceProvider parent)
42
42
_table = parent . _table ;
43
43
}
44
44
45
+ // Reusing _resolvedServices as an implementation detail of the lock
46
+ private object SyncObject => _resolvedServices ;
47
+
45
48
/// <summary>
46
49
/// Gets the service object of the specified type.
47
50
/// </summary>
@@ -138,14 +141,24 @@ internal IServiceCallSite GetResolveCallSite(IService service, ISet<Type> callSi
138
141
139
142
public void Dispose ( )
140
143
{
141
- lock ( _disposables )
144
+ lock ( SyncObject )
142
145
{
143
- foreach ( var disposable in _disposables )
146
+ if ( _transientDisposables != null )
147
+ {
148
+ foreach ( var disposable in _transientDisposables )
149
+ {
150
+ disposable . Dispose ( ) ;
151
+ }
152
+
153
+ _transientDisposables . Clear ( ) ;
154
+ }
155
+
156
+ // Nuke the other service types
157
+ foreach ( var item in _resolvedServices . Values )
144
158
{
145
- disposable . Dispose ( ) ;
159
+ ( item as IDisposable ) ? . Dispose ( ) ;
146
160
}
147
161
148
- _disposables . Clear ( ) ;
149
162
_resolvedServices . Clear ( ) ;
150
163
}
151
164
}
@@ -163,9 +176,14 @@ private object CaptureDisposable(object service)
163
176
var disposable = service as IDisposable ;
164
177
if ( disposable != null )
165
178
{
166
- lock ( _disposables )
179
+ lock ( SyncObject )
167
180
{
168
- _disposables . Add ( disposable ) ;
181
+ if ( _transientDisposables == null )
182
+ {
183
+ _transientDisposables = new List < IDisposable > ( ) ;
184
+ }
185
+
186
+ _transientDisposables . Add ( disposable ) ;
169
187
}
170
188
}
171
189
}
@@ -262,7 +280,7 @@ public virtual object Invoke(ServiceProvider provider)
262
280
{
263
281
if ( ! provider . _resolvedServices . TryGetValue ( _key , out resolved ) )
264
282
{
265
- resolved = provider . CaptureDisposable ( _serviceCallSite . Invoke ( provider ) ) ;
283
+ resolved = _serviceCallSite . Invoke ( provider ) ;
266
284
provider . _resolvedServices . Add ( _key , resolved ) ;
267
285
}
268
286
}
@@ -287,12 +305,8 @@ public virtual Expression Build(Expression providerExpression)
287
305
keyExpression ,
288
306
resolvedExpression ) ;
289
307
290
- var captureDisposableExpression = Expression . Assign (
291
- resolvedExpression ,
292
- Expression . Call (
293
- providerExpression ,
294
- CaptureDisposableMethodInfo ,
295
- _serviceCallSite . Build ( providerExpression ) ) ) ;
308
+ var assignExpression = Expression . Assign (
309
+ resolvedExpression , _serviceCallSite . Build ( providerExpression ) ) ;
296
310
297
311
var addValueExpression = Expression . Call (
298
312
resolvedServicesExpression ,
@@ -305,7 +319,7 @@ public virtual Expression Build(Expression providerExpression)
305
319
new [ ] { resolvedExpression } ,
306
320
Expression . IfThen (
307
321
Expression . Not ( tryGetValueExpression ) ,
308
- Expression . Block ( captureDisposableExpression , addValueExpression ) ) ,
322
+ Expression . Block ( assignExpression , addValueExpression ) ) ,
309
323
resolvedExpression ) ;
310
324
311
325
return Lock ( providerExpression , blockExpression ) ;
0 commit comments