@@ -8637,9 +8637,12 @@ public static T New<T>(this IResolver resolver, Made.TypedMade<T> made,
8637
8637
public static Expression CreateResolutionExpression(Request request,
8638
8638
bool openResolutionScope = false, bool asResolutionCall = false)
8639
8639
{
8640
- if (request.Rules.DependencyResolutionCallExprs != null &&
8641
- request.Factory != null && !request.Factory.HasRuntimeState)
8642
- PopulateDependencyResolutionCallExpressions(request);
8640
+ if (request.Rules.DependencyResolutionCallExprs != null)
8641
+ {
8642
+ var f = request.Factory;
8643
+ if (f != null && !f.HasRuntimeState)
8644
+ PopulateDependencyResolutionCallExpressions(request);
8645
+ }
8643
8646
8644
8647
var container = request.Container;
8645
8648
var serviceType = request.ServiceType;
@@ -9466,18 +9469,18 @@ public static Request Create(IContainer container, ServiceInfo serviceInfo,
9466
9469
9467
9470
// inherit some flags and service details from parent (if any)
9468
9471
preResolveParent = preResolveParent ?? Empty;
9469
- if (!preResolveParent.IsEmpty)
9472
+ if (preResolveParent.IsEmpty)
9473
+ flags |= preResolveParent.Flags; //inherits the OpensResolutionScope flag in case of Request.EmptyOpensResolutionScope
9474
+ else
9470
9475
{
9471
9476
var parentServiceInfo = preResolveParent.ServiceTypeOrInfo;
9472
9477
if (parentServiceInfo is ServiceInfo ps && ps.Details != null && ps.Details != ServiceDetails.Default)
9473
9478
serviceInfo = serviceInfo.InheritInfoFromDependencyOwner(ps.ServiceType, ps.Details, container, preResolveParent.FactoryType);
9474
9479
9475
- flags |= preResolveParent.Flags & InheritedFlags;
9480
+ flags |= preResolveParent.Flags & InheritedFlags; // filter out flags which are not inherited
9476
9481
}
9477
- else
9478
- flags |= preResolveParent.Flags; //inherits the OpensResolutionScope flag
9479
9482
9480
- var inputArgExprs = inputArgs?.Map(a => Constant(a)); // todo: @check what happens if `a == null`, does the `object` type for is fine
9483
+ var inputArgExprs = inputArgs?.Map(static a => Constant(a)); // todo: @check what happens if `a == null`, does the `object` type for is fine
9481
9484
9482
9485
// we are re-starting the dependency depth count from `1`
9483
9486
var stack = RequestStack.Create();
@@ -9513,64 +9516,68 @@ public static Request Create(IContainer container, Type serviceType,
9513
9516
Request preResolveParent = null, RequestFlags flags = default, object[] inputArgs = null) =>
9514
9517
Create(container, ServiceInfo.Of(serviceType, requiredServiceType, ifUnresolved, serviceKey), preResolveParent, flags, inputArgs);
9515
9518
9516
- /// <summary>Available in runtime only, provides access to container initiated the request.</summary>
9519
+ /// <summary>Available at runtime only, provides an access to container initiated the request.</summary>
9517
9520
public IContainer Container { get; private set; }
9518
9521
9519
9522
/// <summary>Request immediate parent.</summary>
9520
9523
public Request DirectParent;
9521
9524
9522
9525
internal RequestStack RequestStack;
9523
9526
9524
- // mutable because of RequestFlags.AddedToResolutionExpressions
9525
- /// <summary>Persisted request conditions</summary>
9526
- public RequestFlags Flags; // todo: @perf combine with the FactoryType or other numeric fields
9527
-
9528
- // todo: @perf should we unpack the info to the ServiceType and Details (or at least the Details), because we are accessing them via Virtual Calls (and it is a lot)
9529
- // The field is mutable so that the ServiceKey or IfUnresolved can be changed in place.
9527
+ // todo: @perf should we unpack the info to the ServiceType and Details (or at least the Details), because we are accessing them via virtual calls (and there are a lot)
9528
+ // The field is mutable so that the service details ServiceKey or IfUnresolved can be changed in place.
9530
9529
internal object ServiceTypeOrInfo; // the Type or the ServiceInfo
9530
+ private Type _actualServiceType; // the actual service type may in fact be the same as ServiceTypeOrInfo
9531
9531
9532
9532
/// <summary>Input arguments provided with `Resolve`</summary>
9533
9533
internal Expression[] InputArgExprs;
9534
9534
9535
- /// <summary>Runtime known resolve factory, otherwise is <c>null</c></summary>
9536
- internal Factory Factory => _factoryOrImplType as Factory;
9535
+ /// <summary>Service reuse.</summary>
9536
+ public IReuse Reuse { get; private set; }
9537
+
9538
+ internal object _factoryOrImplType;
9539
+
9540
+ /// <summary>Constructor selected by the reflection factory</summary>
9541
+ public ConstructorInfo SelectedConstructor { get; internal set; }
9537
9542
9538
9543
/// <summary>Resolved factory ID, used to identify applied decorator.</summary>
9539
9544
public int FactoryID { get; private set; }
9540
9545
9546
+ /// <summary>ID of decorated factory in case of decorator factory type</summary>
9547
+ public int DecoratedFactoryID { get; private set; } // todo: @perf can we remove or combine it with the other fields?
9548
+
9541
9549
// based on the parent(s) and current request FactoryID
9542
9550
private int _hashCode; // todo: @perf do we need to calculate and store the hash code if it is not used
9543
9551
9544
9552
/// <summary>Type of factory: Service, Wrapper, or Decorator.</summary>
9545
9553
public FactoryType FactoryType { get; private set; }
9546
9554
9555
+ // mutable because of RequestFlags.AddedToResolutionExpressions
9556
+ /// <summary>Persisted request conditions</summary>
9557
+ public RequestFlags Flags; // todo: @perf combine with the FactoryType or other numeric fields
9558
+
9559
+ /// <summary>Number of nested dependencies. Set with each new Push.</summary>
9560
+ public int DependencyDepth; // todo: @perf combine with the DependencyCount or other fields, use the ObjectLayoutInspector to check the layout
9561
+
9562
+ /// <summary>The total dependency count</summary>
9563
+ public int DependencyCount; // todo: @perf combine with the DependencyDepth or other fields
9564
+
9547
9565
/// <summary>Combines decorator and <see cref="DecoratedFactoryID"/></summary>
9548
9566
public int CombineDecoratorWithDecoratedFactoryID() => FactoryID | (DecoratedFactoryID << 16);
9549
9567
9550
- /// <summary>Service implementation type if known.</summary>
9551
- public Type ImplementationType => _factoryOrImplType as Type ?? Factory?.ImplementationType;
9552
-
9553
- internal object _factoryOrImplType;
9568
+ /// <summary>Runtime known resolve factory, otherwise is <c>null</c></summary>
9569
+ internal Factory Factory => _factoryOrImplType as Factory;
9554
9570
9571
+ /// <summary>Service implementation type if known.</summary>
9572
+ public Type ImplementationType => _factoryOrImplType as Type ?? (_factoryOrImplType as Factory)?.ImplementationType;
9573
+
9555
9574
/// <summary>Sets the service factory already resolved by the wrapper to save for the future factory resolution</summary>
9556
9575
public Request WithWrappedServiceFactory(Factory f)
9557
9576
{
9558
9577
_factoryOrImplType = f;
9559
9578
return this;
9560
9579
}
9561
9580
9562
- /// <summary>Service reuse.</summary>
9563
- public IReuse Reuse { get; private set; }
9564
-
9565
- /// <summary>ID of decorated factory in case of decorator factory type</summary>
9566
- public int DecoratedFactoryID { get; private set; } // todo: @perf can we remove or combine it with the other fields?
9567
-
9568
- /// <summary>Number of nested dependencies. Set with each new Push.</summary>
9569
- public int DependencyDepth; // todo: @perf combine with theDependencyCount or other fields, use the ObjectLayoutInspector to check the layout
9570
-
9571
- /// <summary>The total dependency count</summary>
9572
- public int DependencyCount; // todo: @perf combine with the DependencyDepth or other fields
9573
-
9574
9581
internal void DecreaseTrackedDependencyCountForParents(int dependencyCount)
9575
9582
{
9576
9583
for (var p = DirectParent; !p.IsEmpty; p = p.DirectParent)
@@ -9642,7 +9649,6 @@ public Request Parent
9642
9649
9643
9650
/// <summary>Compatible required or service type.</summary>
9644
9651
public Type GetActualServiceType() => _actualServiceType;
9645
- private Type _actualServiceType;
9646
9652
9647
9653
/// <summary>Get the details</summary>
9648
9654
public ServiceDetails GetServiceDetails() => ServiceTypeOrInfo is ServiceInfo i ? i.Details : ServiceDetails.Default;
@@ -9660,7 +9666,7 @@ public Request Parent
9660
9666
public int ReuseLifespan => Reuse?.Lifespan ?? 0;
9661
9667
9662
9668
/// <summary>Known implementation, or otherwise actual service type.</summary>
9663
- public Type GetKnownImplementationOrServiceType() => _factoryOrImplType as Type ?? Factory?. ImplementationType ?? _actualServiceType;
9669
+ public Type GetKnownImplementationOrServiceType() => ImplementationType ?? _actualServiceType;
9664
9670
9665
9671
private ref Request GetOrPushPooledRequest(RequestStack stack, int indexInStack)
9666
9672
{
@@ -10120,8 +10126,9 @@ public StringBuilder PrintCurrent(StringBuilder s = null)
10120
10126
10121
10127
s.Append(ServiceTypeOrInfo is ParameterInfo pi ? ParameterServiceInfo.Of(pi) : ServiceTypeOrInfo);
10122
10128
10123
- if (Factory != null && Factory is ReflectionFactory == false)
10124
- s.Append(' ').Append(Factory.GetType().Name).Append(' ');
10129
+ var f = Factory;
10130
+ if (f != null && f is ReflectionFactory == false)
10131
+ s.Append(' ').Append(f.GetType().Name).Append(' ');
10125
10132
10126
10133
if (FactoryID != 0)
10127
10134
s.Append(" FactoryId=").Append(FactoryID);
@@ -10250,6 +10257,7 @@ private void SetServiceInfo(IContainer container, Request parent, int dependency
10250
10257
Flags = flags;
10251
10258
// resets the factory info:
10252
10259
_factoryOrImplType = null;
10260
+ SelectedConstructor = null;
10253
10261
Reuse = null;
10254
10262
FactoryID = 0;
10255
10263
DecoratedFactoryID = 0;
@@ -10260,6 +10268,7 @@ private void SetServiceInfo(IContainer container, Request parent, int dependency
10260
10268
private void SetResolvedFactory(object factoryOrImplType, int factoryID, FactoryType factoryType, IReuse reuse, int decoratedFactoryID)
10261
10269
{
10262
10270
_factoryOrImplType = factoryOrImplType;
10271
+ SelectedConstructor = null;
10263
10272
FactoryID = factoryID;
10264
10273
FactoryType = factoryType;
10265
10274
Reuse = reuse;
@@ -11830,14 +11839,17 @@ public override Expression CreateExpressionOrDefault(Request request)
11830
11839
var ctorOrMember = factoryMethod.ConstructorOrMethodOrMember;
11831
11840
if (factoryMethod.ResolvedParameterExpressions != null)
11832
11841
{
11842
+ ctor = (ConstructorInfo)ctorOrMember;
11843
+ request.SelectedConstructor = ctor;
11844
+
11833
11845
if (rules.UsedForValidation)
11834
11846
{
11835
11847
TryGetMemberAssignments(ref failedToGetMember, request, container, rules);
11836
11848
return request.GetActualServiceType().GetDefaultValueExpression();
11837
11849
}
11838
11850
11839
11851
var assignements = TryGetMemberAssignments(ref failedToGetMember, request, container, rules);
11840
- var newExpr = New((ConstructorInfo)ctorOrMember , factoryMethod.ResolvedParameterExpressions);
11852
+ var newExpr = New(ctor , factoryMethod.ResolvedParameterExpressions);
11841
11853
return failedToGetMember ? null : assignements == null ? newExpr : (Expression)MemberInit(newExpr, assignements);
11842
11854
}
11843
11855
@@ -11846,10 +11858,12 @@ public override Expression CreateExpressionOrDefault(Request request)
11846
11858
return ConvertExpressionIfNeeded(
11847
11859
ctorOrMember is PropertyInfo p ? Property(factoryExpr, p) : Field(factoryExpr, (FieldInfo)ctorOrMember), request, ctorOrMember);
11848
11860
11849
- ctor = ctorOrMember as ConstructorInfo;
11850
- method = ctorOrMember as MethodInfo;
11861
+ ctor = ctorOrMethod as ConstructorInfo;
11862
+ method = ctorOrMethod as MethodInfo;
11851
11863
}
11852
11864
11865
+ request.SelectedConstructor = ctor;
11866
+
11853
11867
var parameters = ctorOrMethod.GetParameters();
11854
11868
if (parameters.Length == 0)
11855
11869
{
0 commit comments