Skip to content

Commit b82c4f0

Browse files
authored
fixing dryioc IServiceProvider scoping issues (#8388)
1 parent 5b35e67 commit b82c4f0

File tree

5 files changed

+327
-46
lines changed

5 files changed

+327
-46
lines changed

src/WebJobs.Script.WebHost/DependencyInjection/DryIoc/Container.cs

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ object IResolver.Resolve(Type serviceType, object serviceKey,
251251

252252
var currentScopeName = CurrentScope?.Name;
253253
if (currentScopeName != null)
254-
cacheContextKey = cacheContextKey == null
254+
cacheContextKey = cacheContextKey == null
255255
? currentScopeName
256256
: KV.Of(cacheContextKey, currentScopeName);
257257

@@ -627,7 +627,7 @@ void IResolverContext.UseInstance(Type serviceType, object instance, IfAlreadyRe
627627
var oldFactory = oldEntry as Factory;
628628
if (oldFactory != null)
629629
registry.DropFactoryCache(oldFactory, serviceType);
630-
else
630+
else
631631
((FactoriesEntry)oldEntry).Factories.Enumerate().ToArray()
632632
.DoPer(x => registry.DropFactoryCache(x.Value, serviceType, serviceKey));
633633
}
@@ -701,7 +701,7 @@ public IContainer With(Rules rules, IScopeContext scopeContext, RegistrySharing
701701
/// <param name="ignoreInsteadOfThrow">(optional) Controls what to do with the next registration: ignore or throw exception.
702702
/// Throws exception by default.</param>
703703
public IContainer WithNoMoreRegistrationAllowed(bool ignoreInsteadOfThrow = false) =>
704-
new Container(Rules,
704+
new Container(Rules,
705705
Ref.Of(_registry.Value.WithNoMoreRegistrationAllowed(ignoreInsteadOfThrow)),
706706
_singletonScope, _scopeContext, _ownCurrentScope,
707707
_disposed, _disposeStackTrace, _parent, _root);
@@ -773,7 +773,7 @@ Factory IContainer.GetServiceFactoryOrDefault(Request request)
773773
Type serviceType;
774774
var requiredServiceType = request.RequiredServiceType;
775775
if (requiredServiceType != null && requiredServiceType.IsOpenGeneric())
776-
serviceType = requiredServiceType;
776+
serviceType = requiredServiceType;
777777
else
778778
{
779779
// Special case when open-generic required service type is encoded in ServiceKey as array of { ReqOpenGenServiceType, ServiceKey }
@@ -826,7 +826,7 @@ Factory IContainer.GetServiceFactoryOrDefault(Request request)
826826
if (matchedFactories.Length == 1)
827827
{
828828
// Changes service key for resolution call to identify single factory in cache and prevent wrong hit
829-
if (defaultFactories.Length > 1 && request.IsResolutionCall)
829+
if (defaultFactories.Length > 1 && request.IsResolutionCall)
830830
request.ChangeServiceKey(matchedFactories[0].Key);
831831

832832
return matchedFactories[0].Value;
@@ -919,7 +919,7 @@ Expr IContainer.GetDecoratorExpressionOrDefault(Request request)
919919

920920
var arrayElementType = request.ServiceType.GetArrayElementTypeOrNull();
921921
if (arrayElementType != null)
922-
request = request.WithChangedServiceInfo(x =>
922+
request = request.WithChangedServiceInfo(x =>
923923
x.With(typeof(IEnumerable<>).MakeGenericType(arrayElementType)));
924924

925925
var container = request.Container;
@@ -1176,7 +1176,7 @@ private KV<object, Factory>[] GetRegisteredServiceFactoriesOrNull(Type serviceTy
11761176
return null;
11771177

11781178
var factory = entry as Factory;
1179-
return factory != null
1179+
return factory != null
11801180
? new KV<object, Factory>(DefaultKey.Value, factory).One()
11811181
: ((FactoriesEntry)entry).Factories.Enumerate().ToArray();
11821182
}
@@ -1402,13 +1402,18 @@ private Factory GetWrapperFactoryOrDefault(Request request)
14021402
return factory;
14031403
}
14041404

1405+
internal void SetScopedProvider(IServiceProvider serviceProvider)
1406+
{
1407+
_scopedProvider = serviceProvider;
1408+
}
1409+
14051410
#endregion
14061411

14071412
#region Implementation
14081413

14091414
private int _disposed;
14101415
private StackTrace _disposeStackTrace;
1411-
1416+
private IServiceProvider _scopedProvider;
14121417
internal readonly Ref<Registry> _registry;
14131418

14141419
private readonly IScope _singletonScope;
@@ -1422,6 +1427,8 @@ private Factory GetWrapperFactoryOrDefault(Request request)
14221427

14231428
internal bool PreferInterpretation => _preferInterpretation;
14241429

1430+
public IServiceProvider ScopedServiceProvider => _scopedProvider;
1431+
14251432
internal sealed class InstanceFactory : Factory
14261433
{
14271434
public override Type ImplementationType { get; }
@@ -1791,14 +1798,14 @@ public Registry Unregister(FactoryType factoryType, Type serviceType, object ser
17911798
Factory removedWrapper = null;
17921799
var registry = WithWrappers(Wrappers.Update(serviceType, null, (factory, _null) =>
17931800
{
1794-
if (factory != null && condition != null && !condition(factory))
1801+
if (factory != null && condition != null && !condition(factory))
17951802
return factory;
17961803
removedWrapper = factory;
17971804
return null;
17981805

17991806
}));
18001807

1801-
if (removedWrapper == null)
1808+
if (removedWrapper == null)
18021809
return this;
18031810
registry.DropFactoryCache(removedWrapper, serviceType);
18041811
return registry;
@@ -1811,7 +1818,7 @@ public Registry Unregister(FactoryType factoryType, Type serviceType, object ser
18111818
return removedDecorators == factories ? null : factories.Except(removedDecorators).ToArray();
18121819
}));
18131820

1814-
if (removedDecorators.IsNullOrEmpty())
1821+
if (removedDecorators.IsNullOrEmpty())
18151822
return this;
18161823

18171824
foreach (var removedDecorator in removedDecorators)
@@ -1908,7 +1915,7 @@ private Registry UnregisterServiceFactory(Type serviceType, object serviceKey =
19081915

19091916
internal void DropFactoryCache(Factory factory, Type serviceType, object serviceKey = null)
19101917
{
1911-
if (!DefaultFactoryDelegateCache.Value.IsEmpty ||
1918+
if (!DefaultFactoryDelegateCache.Value.IsEmpty ||
19121919
!KeyedFactoryDelegateCache.Value.IsEmpty)
19131920
{
19141921
if (factory.FactoryGenerator == null)
@@ -1943,7 +1950,7 @@ private Container(Rules rules, Ref<Registry> registry, IScope singletonScope,
19431950
_registry = registry;
19441951

19451952
_singletonScope = singletonScope;
1946-
1953+
19471954
_scopeContext = scopeContext;
19481955

19491956
if (_scopeContext == null && !FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableEnhancedScopes))
@@ -2000,7 +2007,7 @@ public override bool Equals(object obj)
20002007
public override int GetHashCode() => ImTools.HashCode.Combine(RequiredServiceType, ServiceKey);
20012008

20022009
/// <inheritdoc />
2003-
public Expr ToExpression(Func<object, Expr> fallbackConverter) =>
2010+
public Expr ToExpression(Func<object, Expr> fallbackConverter) =>
20042011
New(_ctor, Constant(RequiredServiceType, typeof(Type)), fallbackConverter(ServiceKey));
20052012

20062013
private static readonly ConstructorInfo _ctor = typeof(OpenGenericTypeKey).SingleConstructor();
@@ -3762,7 +3769,7 @@ public static FactoryMethodSelector Constructor(bool mostResolvable = false, boo
37623769

37633770
// First the check for normal resolution without Func<a, b, c>
37643771
if (!request.IsWrappedInFuncWithArgs())
3765-
return Of(ctorsWithMaxParamsFirst.FindFirst(x =>
3772+
return Of(ctorsWithMaxParamsFirst.FindFirst(x =>
37663773
x.GetParameters().FindFirst(p => !IsResolvableParameter(p, paramSelector, request)) == null)
37673774
.ThrowIfNull(Error.UnableToFindCtorWithAllResolvableArgs, request));
37683775

@@ -3832,7 +3839,7 @@ public static FactoryMethodSelector Constructor(bool mostResolvable = false, boo
38323839
};
38333840

38343841
/// <summary>Easy way to specify default constructor to be used for resolution.</summary>
3835-
public static FactoryMethodSelector DefaultConstructor(bool includeNonPublic = false) => request =>
3842+
public static FactoryMethodSelector DefaultConstructor(bool includeNonPublic = false) => request =>
38363843
request.ImplementationType.ThrowIfNull(Error.ImplTypeIsNotSpecifiedForAutoCtorSelection, request)
38373844
.GetConstructorOrNull(includeNonPublic, Empty<Type>())
38383845
?.Do(ctor => Of(ctor));
@@ -4055,12 +4062,12 @@ private static TypedMade<TService> FromExpression<TService>(
40554062
var hasCustomValue = false;
40564063

40574064
var parameterSelector = parameters.IsNullOrEmpty() ? null
4058-
: ComposeParameterSelectorFromArgs(ref hasCustomValue,
4065+
: ComposeParameterSelectorFromArgs(ref hasCustomValue,
40594066
serviceReturningExpr, parameters, argExprs, argValues);
40604067

40614068
var propertiesAndFieldsSelector =
40624069
memberBindingExprs == null || memberBindingExprs.Count == 0 ? null
4063-
: ComposePropertiesAndFieldsSelector(ref hasCustomValue,
4070+
: ComposePropertiesAndFieldsSelector(ref hasCustomValue,
40644071
serviceReturningExpr, memberBindingExprs, argValues);
40654072

40664073
return new TypedMade<TService>(factoryMethod, parameterSelector, propertiesAndFieldsSelector, hasCustomValue);
@@ -4089,7 +4096,7 @@ private Made(FactoryMethodSelector factoryMethod = null, ParameterSelector param
40894096
}
40904097

40914098
private static ParameterSelector ComposeParameterSelectorFromArgs(ref bool hasCustomValue,
4092-
Expression wholeServiceExpr, ParameterInfo[] paramInfos, IList<Expression> argExprs,
4099+
Expression wholeServiceExpr, ParameterInfo[] paramInfos, IList<Expression> argExprs,
40934100
params Func<Request, object>[] argValues)
40944101
{
40954102
var paramSelector = DryIoc.Parameters.Of;
@@ -4174,7 +4181,7 @@ private static PropertiesAndFieldsSelector ComposePropertiesAndFieldsSelector(re
41744181
}
41754182

41764183
private static Func<Request, object> GetArgCustomValueProvider(
4177-
Expression wholeServiceExpr, MethodCallExpression methodCallExpr, Func<Request, object>[] argValues)
4184+
Expression wholeServiceExpr, MethodCallExpression methodCallExpr, Func<Request, object>[] argValues)
41784185
{
41794186
Throw.If(argValues.IsNullOrEmpty(), Error.ArgValueIndexIsProvidedButNoArgValues, wholeServiceExpr);
41804187

@@ -4925,7 +4932,7 @@ private static void PopulateDependencyResolutionCallExpressions(Request request)
49254932
if (factoryExpr == null)
49264933
return;
49274934

4928-
request.Container.Rules.DependencyResolutionCallExprs.Swap(x =>
4935+
request.Container.Rules.DependencyResolutionCallExprs.Swap(x =>
49294936
x.AddOrUpdate(request, factoryExpr
49304937
#if FEC_EXPRESSION_INFO
49314938
.ToExpression()
@@ -5383,7 +5390,7 @@ public override IServiceInfo Create(Type serviceType, ServiceDetails details) =>
53835390

53845391
public override void SetValue(object holder, object value) => _property.SetValue(holder, value, null);
53855392

5386-
public override string ToString() =>
5393+
public override string ToString() =>
53875394
new StringBuilder().Print(this).Append(" as property ").Print(_property.Name, "\"").ToString();
53885395

53895396
private readonly PropertyInfo _property;
@@ -5409,7 +5416,7 @@ private class Field : PropertyOrFieldServiceInfo
54095416
{
54105417
public override Type ServiceType => _field.FieldType;
54115418

5412-
public override IServiceInfo Create(Type serviceType, ServiceDetails details) =>
5419+
public override IServiceInfo Create(Type serviceType, ServiceDetails details) =>
54135420
serviceType == null ? new WithDetails(_field, details) : new TypeWithDetails(_field, serviceType, details);
54145421

54155422
public override MemberInfo Member => _field;
@@ -5630,7 +5637,7 @@ public Request Parent
56305637
public Type ServiceType => _serviceInfo.ServiceType;
56315638

56325639
/// <summary>Compatible required or service type.</summary>
5633-
public Type GetActualServiceType() =>
5640+
public Type GetActualServiceType() =>
56345641
_actualServiceType ?? (_actualServiceType = _serviceInfo.GetActualServiceType());
56355642

56365643
private Type _actualServiceType; // saving result once
@@ -5672,8 +5679,8 @@ public Request Push(IServiceInfo info, RequestFlags additionalFlags = DefaultFla
56725679

56735680
/// <summary>Composes service description into <see cref="IServiceInfo"/> and Pushes the new request.</summary>
56745681
public Request Push(Type serviceType, object serviceKey = null,
5675-
IfUnresolved ifUnresolved = IfUnresolved.Throw, Type requiredServiceType = null, RequestFlags flags = DefaultFlags) =>
5676-
Push(ServiceInfo.Of(serviceType.ThrowIfNull().ThrowIf(serviceType.IsOpenGeneric(), Error.ResolvingOpenGenericServiceTypeIsNotPossible),
5682+
IfUnresolved ifUnresolved = IfUnresolved.Throw, Type requiredServiceType = null, RequestFlags flags = DefaultFlags) =>
5683+
Push(ServiceInfo.Of(serviceType.ThrowIfNull().ThrowIf(serviceType.IsOpenGeneric(), Error.ResolvingOpenGenericServiceTypeIsNotPossible),
56775684
requiredServiceType, ifUnresolved, serviceKey), flags);
56785685

56795686
#region Used in generated expression
@@ -5776,7 +5783,7 @@ public Request WithResolvedFactory(Factory factory,
57765783
}
57775784

57785785
// checking the service types only cause wrapper and decorators may be used multiple times
5779-
if (!skipRecursiveDependencyCheck &&
5786+
if (!skipRecursiveDependencyCheck &&
57805787
factory.FactoryType == FactoryType.Service &&
57815788
HasRecursiveParent(factory.FactoryID))
57825789
Throw.It(Error.RecursiveDependencyDetected, Print(factory.FactoryID));
@@ -6529,7 +6536,7 @@ public virtual Expr GetExpressionOrDefault(Request request)
65296536
!request.IsResolutionCall && // preventing recursion
65306537
(Setup.AsResolutionCall || Setup.UseParentReuse || request.ShouldSplitObjectGraph()) &&
65316538
request.GetActualServiceType() != typeof(void)))
6532-
return Resolver.CreateResolutionExpression(request, Setup.OpenResolutionScope);
6539+
return Resolver.CreateResolutionExpression(request, Setup.OpenResolutionScope);
65336540

65346541
// First look for decorators if it is not already a decorator
65356542
if (FactoryType != FactoryType.Decorator)
@@ -7083,14 +7090,14 @@ public override Expr CreateExpressionOrDefault(Request request)
70837090
var paramExpr = paramFactory?.GetExpressionOrDefault(paramRequest);
70847091
if (paramExpr == null ||
70857092
// When param is an empty array / collection, then we may use a default value instead (#581)
7086-
paramInfo.Details.DefaultValue != null &&
7093+
paramInfo.Details.DefaultValue != null &&
70877094
paramExpr.NodeType == ExpressionType.NewArrayInit && ((NewArrayExpr)paramExpr).Expressions.Count == 0)
70887095
{
70897096
// Check if parameter dependency itself (without propagated parent details)
70907097
// does not allow default, then stop checking the rest of parameters.
70917098
if (paramInfo.Details.IfUnresolved == IfUnresolved.Throw)
70927099
return null;
7093-
7100+
70947101
var defaultValue = paramInfo.Details.DefaultValue;
70957102
paramExpr = defaultValue != null
70967103
? container.GetConstantExpression(defaultValue)
@@ -7247,10 +7254,10 @@ public Factory GetGeneratedFactory(Request request, bool ifErrorReturnDefault =
72477254

72487255
if (implType != null)
72497256
{
7250-
implType = implType.IsGenericParameter
7257+
implType = implType.IsGenericParameter
72517258
? closedTypeArgs[0]
72527259
: Throw.IfThrows<ArgumentException, Type>(
7253-
() => implType.MakeGenericType(closedTypeArgs),
7260+
() => implType.MakeGenericType(closedTypeArgs),
72547261
!ifErrorReturnDefault && request.IfUnresolved == IfUnresolved.Throw,
72557262
Error.NoMatchedGenericParamConstraints, implType, request);
72567263
if (implType == null)
@@ -7479,7 +7486,7 @@ private static void MatchOpenGenericConstraints(Type[] implTypeParams, Type[] im
74797486
continue; // skip yet unknown type arg
74807487

74817488
var implTypeParamConstraints = implTypeParams[i].GetGenericParamConstraints();
7482-
if (implTypeParamConstraints.IsNullOrEmpty())
7489+
if (implTypeParamConstraints.IsNullOrEmpty())
74837490
continue; // skip case with no constraints
74847491

74857492
// match type parameters inside constraint
@@ -7843,7 +7850,7 @@ private object TryGetOrAdd(ImMap<object> items, int id, CreateScopedValue create
78437850
lock (_locker)
78447851
{
78457852
// re-check if items where changed in between (double check locking)
7846-
if (_items != items && _items.TryFind(id, out item))
7853+
if (_items != items && _items.TryFind(id, out item))
78477854
return item;
78487855

78497856
item = createValue();
@@ -8067,7 +8074,7 @@ public Expr Apply(Request request, Expr serviceFactoryExpr) =>
80678074
Constant(request.FactoryID), Lambda<CreateScopedValue>(serviceFactoryExpr),
80688075
Constant(request.Factory.Setup.DisposalOrder));
80698076

8070-
private static readonly Lazy<Expr> _singletonReuseExpr = Lazy.Of<Expr>(() =>
8077+
private static readonly Lazy<Expr> _singletonReuseExpr = Lazy.Of<Expr>(() =>
80718078
Field(null, typeof(Reuse).Field(nameof(Reuse.Singleton))));
80728079

80738080
/// <inheritdoc />
@@ -8268,11 +8275,11 @@ private ResolutionScopeName(Type serviceType, object serviceKey)
82688275
public bool Match(object scopeName)
82698276
{
82708277
var name = scopeName as ResolutionScopeName;
8271-
return name != null &&
8278+
return name != null &&
82728279
(ServiceType == null ||
82738280
name.ServiceType.IsAssignableTo(ServiceType) ||
8274-
ServiceType.IsOpenGeneric() &&
8275-
name.ServiceType.GetGenericDefinitionOrNull().IsAssignableTo(ServiceType)) &&
8281+
ServiceType.IsOpenGeneric() &&
8282+
name.ServiceType.GetGenericDefinitionOrNull().IsAssignableTo(ServiceType)) &&
82768283
(ServiceKey == null || ServiceKey.Equals(name.ServiceKey));
82778284
}
82788285

@@ -8304,7 +8311,7 @@ public static class Reuse
83048311

83058312
/// <summary>Scoped to multiple names.</summary>
83068313
public static IReuse ScopedTo(params object[] names) =>
8307-
names.IsNullOrEmpty() ? Scoped
8314+
names.IsNullOrEmpty() ? Scoped
83088315
: names.Length == 1 ? ScopedTo(names[0]) : new CurrentScopeReuse(CompositeScopeName.Of(names));
83098316

83108317
/// <summary>Same as InResolutionScopeOf. From now on will be the default name.</summary>
@@ -8535,6 +8542,8 @@ public enum RegistrySharing
85358542
/// <summary>Combines registrator and resolver roles, plus rules and scope management.</summary>
85368543
public interface IContainer : IRegistrator, IResolverContext
85378544
{
8545+
IServiceProvider ScopedServiceProvider { get; }
8546+
85388547
/// <summary>Rules for defining resolution/registration behavior throughout container.</summary>
85398548
Rules Rules { get; }
85408549

@@ -9538,7 +9547,7 @@ public static StringBuilder Print(this StringBuilder s, IEnumerable items,
95389547
/// <paramref name="getTypeName"/>Allows to specify if you want Name instead of FullName.</summary>
95399548
public static StringBuilder Print(this StringBuilder s, Type type, Func<Type, string> getTypeName = null)
95409549
{
9541-
if (type == null)
9550+
if (type == null)
95429551
return s;
95439552

95449553
var isArray = type.IsArray;

0 commit comments

Comments
 (0)