ResolutionContext
Represents information about the actual resolution flow.
using Stashbox.Entity;
using Stashbox.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Stashbox.Resolution
{
public class ResolutionContext
{
private readonly HashTree<Expression> expressionCache;
private readonly HashTree<Func<IResolutionScope, object>> factoryCache;
private readonly HashTree<Type, HashTree<object, Expression>> expressionOverrides;
private readonly HashTree<Type, Type> currentlyDecoratingTypes;
private readonly HashTree<bool> circularDependencyBarrier;
public bool NullResultAllowed { get; }
public ParameterExpression CurrentScopeParameter { get; set; }
internal IContainerContext RequestInitiatorContainerContext { get; set; }
internal IContainerContext CurrentContainerContext { get; set; }
internal ExpandableArray<Expression> SingleInstructions { get; set; }
internal HashTree<ParameterExpression> DefinedVariables { get; set; }
internal bool ExpressionCacheEnabled { get; set; }
internal bool FactoryDelegateCacheEnabled { get; set; }
internal ExpandableArray<object> ScopeNames { get; }
internal ExpandableArray<KeyValue<bool, ParameterExpression>[]> ParameterExpressions { get; }
internal ResolutionContext(IEnumerable<object> initialScopeNames, IContainerContext currentContainerContext, bool nullResultAllowed = false, HashTree<Type, HashTree<object, Expression>> dependencyOverrides = null)
{
DefinedVariables = new HashTree<ParameterExpression>();
SingleInstructions = new ExpandableArray<Expression>();
expressionOverrides = (dependencyOverrides ?? new HashTree<Type, HashTree<object, Expression>>());
currentlyDecoratingTypes = new HashTree<Type, Type>();
NullResultAllowed = nullResultAllowed;
CurrentScopeParameter = Constants.ResolutionScopeParameter;
ParameterExpressions = new ExpandableArray<KeyValue<bool, ParameterExpression>[]>();
ScopeNames = ExpandableArray<object>.FromEnumerable(initialScopeNames);
circularDependencyBarrier = new HashTree<bool>();
expressionCache = new HashTree<Expression>();
factoryCache = new HashTree<Func<IResolutionScope, object>>();
FactoryDelegateCacheEnabled = (dependencyOverrides == null);
CurrentContainerContext = currentContainerContext;
}
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(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 bool IsCurrentlyDecorating(Type type)
{
return currentlyDecoratingTypes.GetOrDefault(type, true) != (Type)null;
}
internal void AddCurrentlyDecoratingType(Type type)
{
currentlyDecoratingTypes.Add(type, type, true);
}
internal void ClearCurrentlyDecoratingType(Type type)
{
currentlyDecoratingTypes.Add(type, null, true);
}
internal Expression GetExpressionOverrideOrDefault(Type type, object name = null)
{
return expressionOverrides.GetOrDefault(type, true)?.GetOrDefault(name ?? type, false);
}
internal void SetExpressionOverride(Type type, Expression expression)
{
HashTree<object, Expression> orDefault = expressionOverrides.GetOrDefault(type, true);
if (orDefault != null)
orDefault.Add(type, expression, true);
else
expressionOverrides.Add(type, new HashTree<object, Expression>(type, expression), true);
}
internal void AddParameterExpressions(IEnumerable<ParameterExpression> parameterExpressions)
{
ParameterExpressions.Add((from p in parameterExpressions
select new KeyValue<bool, ParameterExpression>(false, p)).CastToArray());
ExpressionCacheEnabled = false;
}
internal void SetCircularDependencyBarrier(int key, bool value)
{
circularDependencyBarrier.Add(key, value);
}
internal bool GetCircularDependencyBarrier(int key)
{
return circularDependencyBarrier.GetOrDefault(key);
}
internal ResolutionContext BeginCrossContainerContext(IContainerContext requestInitiatorContext, IContainerContext currentContainerContext)
{
ResolutionContext resolutionContext = Clone();
resolutionContext.RequestInitiatorContainerContext = requestInitiatorContext;
resolutionContext.CurrentContainerContext = 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 HashTree<ParameterExpression>();
resolutionContext.SingleInstructions = new ExpandableArray<Expression>();
return resolutionContext;
}
private ResolutionContext Clone()
{
return (ResolutionContext)MemberwiseClone();
}
}
}