ResolutionContext
Represents information about the actual resolution flow.
using Stashbox.Registration;
using Stashbox.Utils;
using Stashbox.Utils.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace Stashbox.Resolution
{
public class ResolutionContext
{
private Tree<Expression> expressionCache;
private readonly Tree<Func<IResolutionScope, object>> factoryCache;
private readonly HashTree<object, Expression> expressionOverrides;
private readonly Stashbox.Utils.Data.Stack<int> circularDependencyBarrier;
internal IContainerContext RequestInitiatorContainerContext { get; }
internal IResolutionStrategy ResolutionStrategy { get; }
internal ExpandableArray<Expression> SingleInstructions { get; set; }
internal Tree<ParameterExpression> DefinedVariables { get; set; }
internal ExpandableArray<Pair<bool, ParameterExpression>[]> ParameterExpressions { get; set; }
internal ExpandableArray<Type, Stashbox.Utils.Data.Stack<ServiceRegistration>> Decorators { get; set; }
internal int CurrentLifeSpan { get; set; }
internal string NameOfServiceLifeSpanValidatingAgainst { get; set; }
internal bool PerResolutionRequestCacheEnabled { get; set; }
internal bool UnknownTypeCheckDisabled { get; set; }
internal bool ShouldFallBackToRequestInitiatorContext { get; set; }
internal bool FactoryDelegateCacheEnabled { get; }
internal ExpandableArray<object> ScopeNames { get; }
public bool NullResultAllowed { get; }
public bool IsRequestedFromRoot { get; }
public ParameterExpression CurrentScopeParameter { get; set; }
public IContainerContext CurrentContainerContext { get; set; }
internal ResolutionContext(IEnumerable<object> initialScopeNames, IContainerContext currentContainerContext, IResolutionStrategy resolutionStrategy, bool isRequestedFromRoot, bool nullResultAllowed = false, HashTree<object, Expression> dependencyOverrides = null, ParameterExpression[] initialParameters = null)
{
DefinedVariables = new Tree<ParameterExpression>();
SingleInstructions = new ExpandableArray<Expression>();
Decorators = new ExpandableArray<Type, Stashbox.Utils.Data.Stack<ServiceRegistration>>();
expressionOverrides = dependencyOverrides;
NullResultAllowed = nullResultAllowed;
CurrentScopeParameter = Constants.ResolutionScopeParameter;
ParameterExpressions = ((initialParameters != null) ? new ExpandableArray<Pair<bool, ParameterExpression>[]> {
initialParameters.AsParameterPairs()
} : new ExpandableArray<Pair<bool, ParameterExpression>[]>());
ScopeNames = initialScopeNames.AsExpandableArray();
circularDependencyBarrier = new Stashbox.Utils.Data.Stack<int>();
expressionCache = new Tree<Expression>();
factoryCache = new Tree<Func<IResolutionScope, object>>();
ResolutionStrategy = resolutionStrategy;
IsRequestedFromRoot = isRequestedFromRoot;
CurrentContainerContext = (RequestInitiatorContainerContext = currentContainerContext);
bool flag2 = PerResolutionRequestCacheEnabled = (dependencyOverrides == null);
FactoryDelegateCacheEnabled = flag2;
}
public void AddInstruction(Expression instruction)
{
SingleInstructions.Add(instruction);
}
public void AddDefinedVariable(int key, ParameterExpression parameter)
{
DefinedVariables.Add(key, parameter);
}
public void AddDefinedVariable(ParameterExpression parameter)
{
DefinedVariables.Add(RuntimeHelpers.GetHashCode(parameter), parameter);
}
public ParameterExpression GetKnownVariableOrDefault(int key)
{
return DefinedVariables.GetOrDefault(key);
}
internal void CacheExpression(int key, Expression expression)
{
expressionCache.Add(key, expression);
}
internal Expression GetCachedExpression(int key)
{
return expressionCache.GetOrDefault(key);
}
internal void CacheFactory(int key, Func<IResolutionScope, object> factory)
{
factoryCache.Add(key, factory);
}
internal Func<IResolutionScope, object> GetCachedFactory(int key)
{
return factoryCache.GetOrDefault(key);
}
internal Expression GetExpressionOverrideOrDefault(Type type, object name = null)
{
return expressionOverrides?.GetOrDefault(name ?? type, false);
}
internal bool WeAreInCircle(int key)
{
return circularDependencyBarrier.Contains(key);
}
internal void PullOutCircularDependencyBarrier(int key)
{
circularDependencyBarrier.Add(key);
}
internal void LetDownCircularDependencyBarrier()
{
circularDependencyBarrier.Pop();
}
internal ResolutionContext BeginCrossContainerContext(IContainerContext currentContainerContext)
{
ResolutionContext resolutionContext = Clone();
resolutionContext.CurrentContainerContext = currentContainerContext;
resolutionContext.ShouldFallBackToRequestInitiatorContext = (resolutionContext.RequestInitiatorContainerContext != currentContainerContext);
return resolutionContext;
}
internal ResolutionContext BeginNewScopeContext(KeyValue<object, ParameterExpression> scopeParameter)
{
ScopeNames.Add(scopeParameter.Key);
ResolutionContext resolutionContext = BeginSubGraph();
resolutionContext.CurrentScopeParameter = scopeParameter.Value;
return resolutionContext;
}
internal ResolutionContext BeginSubGraph()
{
ResolutionContext resolutionContext = Clone();
resolutionContext.DefinedVariables = new Tree<ParameterExpression>();
resolutionContext.SingleInstructions = new ExpandableArray<Expression>();
resolutionContext.expressionCache = new Tree<Expression>();
return resolutionContext;
}
internal ResolutionContext BeginUnknownTypeCheckDisabledContext()
{
ResolutionContext resolutionContext = Clone();
resolutionContext.UnknownTypeCheckDisabled = true;
return resolutionContext;
}
internal ResolutionContext BeginContextWithFunctionParameters(ParameterExpression[] parameterExpressions)
{
ResolutionContext resolutionContext = Clone();
resolutionContext.ParameterExpressions = new ExpandableArray<Pair<bool, ParameterExpression>[]>(ParameterExpressions) {
parameterExpressions.AsParameterPairs()
};
resolutionContext.PerResolutionRequestCacheEnabled = false;
return resolutionContext;
}
internal ResolutionContext BeginDecoratingContext(Type decoratingType, Stashbox.Utils.Data.Stack<ServiceRegistration> serviceRegistrations)
{
ResolutionContext resolutionContext = Clone();
resolutionContext.Decorators = new ExpandableArray<Type, Stashbox.Utils.Data.Stack<ServiceRegistration>>(Decorators);
resolutionContext.Decorators.AddOrUpdate(decoratingType, serviceRegistrations);
return resolutionContext;
}
internal ResolutionContext BeginLifetimeValidationContext(int lifeSpan, string currentlyLifeSpanValidatingService)
{
ResolutionContext resolutionContext = Clone();
resolutionContext.CurrentLifeSpan = lifeSpan;
resolutionContext.NameOfServiceLifeSpanValidatingAgainst = currentlyLifeSpanValidatingService;
return resolutionContext;
}
private ResolutionContext Clone()
{
return (ResolutionContext)MemberwiseClone();
}
}
}