@@ -3321,7 +3321,7 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
3321
3321
{
3322
3322
if (!TryInterpret(resolver, callArgs[2], paramExprs, paramValues, parentArgs, useFec, out var service))
3323
3323
return false;
3324
- result = scope.TrackDisposable( service); // todo: what is with `disposalOrder`
3324
+ result = service is IDisposable d ? scope.TrackDisposableWithoutDisposalOrder(d) : service;
3325
3325
}
3326
3326
3327
3327
return true;
@@ -3336,7 +3336,7 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
3336
3336
{
3337
3337
if (!TryInterpret(resolver, callArgs[3], paramExprs, paramValues, parentArgs, useFec, out var service))
3338
3338
return false;
3339
- result = scope.TrackDisposable(service) ;
3339
+ result = service is IDisposable d ? scope.TrackDisposableWithoutDisposalOrder(d) : service ;
3340
3340
}
3341
3341
3342
3342
return true;
@@ -3359,9 +3359,9 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
3359
3359
{
3360
3360
if (TryInterpret(rc, e, paramExprs, paramValues, parentArgs, uf, out var value))
3361
3361
return value;
3362
- return e.CompileToFactoryDelegate(uf, ((IContainer) rc).Rules.UseInterpretation)(rc);
3362
+ return e.CompileToFactoryDelegate(uf, ((IContainer)rc).Rules.UseInterpretation)(rc);
3363
3363
},
3364
- (int) ConstValue(callArgs[3]));
3364
+ (int)ConstValue(callArgs[3]));
3365
3365
}
3366
3366
3367
3367
return true;
@@ -3372,7 +3372,14 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
3372
3372
r = r.Root ?? r;
3373
3373
if (!TryInterpret(r, callArgs[0], paramExprs, paramValues, parentArgs, useFec, out var service))
3374
3374
return false;
3375
- result = r.SingletonScope.TrackDisposable(service, (int)ConstValue(callArgs[1]));
3375
+ if (service is IDisposable d)
3376
+ {
3377
+ var disposalOrder = (int)ConstValue(callArgs[1]);
3378
+ result = disposalOrder == 0
3379
+ ? r.SingletonScope.TrackDisposableWithoutDisposalOrder(d)
3380
+ : r.SingletonScope.TrackDisposable(service, disposalOrder);
3381
+ }
3382
+
3376
3383
return true;
3377
3384
}
3378
3385
}
@@ -4713,7 +4720,7 @@ public static IResolverContext OpenScope(this IResolverContext r, object name =
4713
4720
var parentScope = r.CurrentScope;
4714
4721
var newOwnScope = new Scope(parentScope, name);
4715
4722
if (trackInParent)
4716
- (parentScope ?? r.SingletonScope).TrackDisposable (newOwnScope);
4723
+ (parentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder (newOwnScope);
4717
4724
return r.WithCurrentScope(newOwnScope);
4718
4725
}
4719
4726
@@ -4722,7 +4729,7 @@ public static IResolverContext OpenScope(this IResolverContext r, object name =
4722
4729
: r.ScopeContext.SetCurrent(parent => new Scope(parent, name));
4723
4730
4724
4731
if (trackInParent)
4725
- (newContextScope.Parent ?? r.SingletonScope).TrackDisposable (newContextScope);
4732
+ (newContextScope.Parent ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder (newContextScope);
4726
4733
return r.WithCurrentScope(null);
4727
4734
}
4728
4735
@@ -4737,7 +4744,7 @@ internal static bool TryGetUsedInstance(this IResolverContext r, Type serviceTyp
4737
4744
// todo: @perf no need to check for IDisposable in TrackDisposable
4738
4745
/// <summary>A bit if sugar to track disposable in the current scope or in the singleton scope as a fallback</summary>
4739
4746
public static T TrackDisposable<T>(this IResolverContext r, T instance) where T : IDisposable =>
4740
- (T)(r.CurrentScope ?? r.SingletonScope).TrackDisposable (instance);
4747
+ (T)(r.CurrentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder (instance);
4741
4748
}
4742
4749
4743
4750
/// <summary>The result delegate generated by DryIoc for service creation.</summary>
@@ -6891,8 +6898,8 @@ public static void RegisterInstance(this IRegistrator registrator, bool isChecke
6891
6898
serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: false);
6892
6899
6893
6900
// done after registration to pass all the registration validation checks
6894
- if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6895
- (registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance );
6901
+ if (instance is IDisposable d && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6902
+ (registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d );
6896
6903
}
6897
6904
6898
6905
/// <summary>
@@ -6945,8 +6952,9 @@ public static void RegisterInstanceMany(this IRegistrator registrator, Type impl
6945
6952
foreach (var serviceType in serviceTypes)
6946
6953
registrator.Register(factory, serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: true);
6947
6954
6948
- if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6949
- (registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance);
6955
+ if (instance is IDisposable d &&
6956
+ (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6957
+ (registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d);
6950
6958
}
6951
6959
6952
6960
/// <summary>
@@ -6986,8 +6994,9 @@ public static void RegisterInstanceMany(this IRegistrator registrator, Type[] se
6986
6994
registrator.Register(factory, serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: true);
6987
6995
}
6988
6996
6989
- if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6990
- (registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance);
6997
+ if (instance is IDisposable d &&
6998
+ (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6999
+ (registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d);
6991
7000
}
6992
7001
6993
7002
/// <summary>List of types excluded by default from RegisterMany convention.</summary>
@@ -11339,11 +11348,13 @@ object TryGetOrAddWithoutClosure(int id,
11339
11348
IResolverContext resolveContext, Expression expr, bool useFec,
11340
11349
Func<IResolverContext, Expression, bool, object> createValue, int disposalOrder = 0);
11341
11350
11342
- // todo: @perf introduce the overload WithoutDisposalOrder
11343
11351
/// <summary>Tracked item will be disposed with the scope.
11344
11352
/// Smaller <paramref name="disposalOrder"/> will be disposed first.</summary>
11345
11353
object TrackDisposable(object item, int disposalOrder = 0);
11346
11354
11355
+ /// <summary>Tracked item will be disposed with the scope.</summary>
11356
+ T TrackDisposableWithoutDisposalOrder<T>(T disposable) where T : IDisposable;
11357
+
11347
11358
///<summary>Sets or adds the service item directly to the scope services</summary>
11348
11359
void SetOrAdd(int id, object item);
11349
11360
@@ -11683,7 +11694,7 @@ public bool TryGet(out object item, int id)
11683
11694
/// <summary>Can be used to manually add service for disposal</summary>
11684
11695
public object TrackDisposable(object item, int disposalOrder = 0)
11685
11696
{
11686
- if (item is IDisposable disposable && disposable != this)
11697
+ if (item is IDisposable disposable && !ReferenceEquals( disposable, this) )
11687
11698
if (disposalOrder == 0)
11688
11699
AddUnorderedDisposable(disposable);
11689
11700
else
@@ -11694,6 +11705,18 @@ public object TrackDisposable(object item, int disposalOrder = 0)
11694
11705
internal static readonly MethodInfo TrackDisposableMethod =
11695
11706
typeof(IScope).GetTypeInfo().GetDeclaredMethod(nameof(IScope.TrackDisposable));
11696
11707
11708
+ /// <summary>Tracked item will be disposed with the scope.</summary>
11709
+ public T TrackDisposableWithoutDisposalOrder<T>(T disposable) where T : IDisposable
11710
+ {
11711
+ if (!ReferenceEquals(disposable, this))
11712
+ {
11713
+ var copy = _unorderedDisposables;
11714
+ if (Interlocked.CompareExchange(ref _unorderedDisposables, copy.Push(disposable), copy) != copy)
11715
+ Ref.Swap(ref _unorderedDisposables, disposable, (x, d) => x.Push(d));
11716
+ }
11717
+ return disposable;
11718
+ }
11719
+
11697
11720
///[Obsolete("Removing because it is not used")]
11698
11721
public void SetUsedInstance(Type type, FactoryDelegate factory) =>
11699
11722
SetUsedInstance(RuntimeHelpers.GetHashCode(type), type, factory);
@@ -11984,7 +12007,6 @@ public Expression Apply(Request request, Expression serviceFactoryExpr)
11984
12007
serviceFactoryExpr = Convert(serviceFactoryExpr, typeof(object));
11985
12008
11986
12009
var resolverContextParamExpr = FactoryDelegateCompiler.ResolverContextParamExpr;
11987
-
11988
12010
if (request.TracksTransientDisposable)
11989
12011
{
11990
12012
if (ScopedOrSingleton)
@@ -12102,7 +12124,7 @@ public static object GetScopedOrSingletonViaFactoryDelegate(IResolverContext r,
12102
12124
/// <summary>Tracks the Unordered disposal in the current scope or in the singleton as fallback</summary>
12103
12125
[MethodImpl((MethodImplOptions)256)]
12104
12126
public static object TrackScopedOrSingleton(IResolverContext r, object item) =>
12105
- (r.CurrentScope ?? r.SingletonScope).TrackDisposable(item) ;
12127
+ item is IDisposable d ? (r.CurrentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder(d) : item ;
12106
12128
12107
12129
internal static readonly MethodInfo TrackScopedOrSingletonMethod =
12108
12130
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackScopedOrSingleton));
@@ -12143,14 +12165,14 @@ public static object GetNameScopedViaFactoryDelegate(IResolverContext r,
12143
12165
12144
12166
/// Subject
12145
12167
public static object TrackScoped(IResolverContext r, bool throwIfNoScope, object item) =>
12146
- r.GetCurrentScope(throwIfNoScope)?.TrackDisposable(item) ;
12168
+ item is IDisposable d ? r.GetCurrentScope(throwIfNoScope)?.TrackDisposableWithoutDisposalOrder(d) : item ;
12147
12169
12148
12170
internal static readonly MethodInfo TrackScopedMethod =
12149
12171
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackScoped));
12150
12172
12151
12173
/// Subject
12152
12174
public static object TrackNameScoped(IResolverContext r, object scopeName, bool throwIfNoScope, object item) =>
12153
- r.GetNamedScope(scopeName, throwIfNoScope)?.TrackDisposable(item) ;
12175
+ item is IDisposable d ? r.GetNamedScope(scopeName, throwIfNoScope)?.TrackDisposableWithoutDisposalOrder(d) : item ;
12154
12176
12155
12177
internal static readonly MethodInfo TrackNameScopedMethod =
12156
12178
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackNameScoped));
0 commit comments