ResolutionStrategy
using Stashbox.Expressions;
using Stashbox.Registration;
using Stashbox.Resolution.Extensions;
using Stashbox.Utils;
using Stashbox.Utils.Data;
using Stashbox.Utils.Data.Immutable;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Stashbox.Resolution
{
internal class ResolutionStrategy : IResolutionStrategy
{
private readonly ExpressionBuilder expressionBuilder;
private ImmutableBucket<IResolver> resolverRepository = ImmutableBucket<IResolver>.Empty;
private ImmutableBucket<IResolver> lastChanceResolverRepository = ImmutableBucket<IResolver>.Empty;
public ResolutionStrategy(ExpressionBuilder expressionBuilder)
{
this.expressionBuilder = expressionBuilder;
}
public Expression BuildExpressionForType(ResolutionContext resolutionContext, TypeInformation typeInformation)
{
if ((object)typeInformation.Type == Constants.ResolverType)
return resolutionContext.CurrentScopeParameter;
if (resolutionContext.ParameterExpressions.Length > 0) {
Type type = typeInformation.Type;
int num = resolutionContext.ParameterExpressions.Length;
while (num-- > 0) {
Pair<bool, ParameterExpression>[] array = resolutionContext.ParameterExpressions[num].WhereOrDefault(delegate(Pair<bool, ParameterExpression> p) {
if ((object)p.I2.Type != type)
return p.I2.Type.Implements(type);
return true;
});
if (array != null) {
Pair<bool, ParameterExpression> obj = array.FirstOrDefault((Pair<bool, ParameterExpression> parameter) => !parameter.I1) ?? array.Last();
obj.I1 = true;
return obj.I2;
}
}
}
if ((object)resolutionContext.DecoratingService.Key == typeInformation.Type)
return resolutionContext.DecoratingService.Value;
Expression expressionOverrideOrDefault = resolutionContext.GetExpressionOverrideOrDefault(typeInformation.Type, typeInformation.DependencyName);
if (expressionOverrideOrDefault != null)
return expressionOverrideOrDefault;
ServiceRegistration registrationOrDefault = resolutionContext.CurrentContainerContext.RegistrationRepository.GetRegistrationOrDefault(typeInformation, resolutionContext);
if (registrationOrDefault == null)
return BuildResolutionExpressionUsingResolvers(typeInformation, resolutionContext);
return expressionBuilder.BuildExpressionAndApplyLifetime(registrationOrDefault, resolutionContext, typeInformation.Type);
}
public IEnumerable<Expression> BuildExpressionsForEnumerableRequest(ResolutionContext resolutionContext, TypeInformation typeInformation)
{
IEnumerable<ServiceRegistration> registrationsOrDefault = resolutionContext.CurrentContainerContext.RegistrationRepository.GetRegistrationsOrDefault(typeInformation, resolutionContext);
ServiceRegistration[] array = (registrationsOrDefault != null) ? registrationsOrDefault.CastToArray() : null;
if (array == null)
return BuildAllResolverExpressionsUsingResolvers(typeInformation, resolutionContext);
int num = array.Length;
Expression[] array2 = new Expression[num];
for (int i = 0; i < num; i++) {
array2[i] = expressionBuilder.BuildExpressionAndApplyLifetime(array[i], resolutionContext, typeInformation.Type);
}
return array2;
}
public Expression BuildExpressionForTopLevelRequest(Type type, object name, ResolutionContext resolutionContext)
{
if ((object)type == Constants.ResolverType)
return resolutionContext.CurrentScopeParameter;
Expression expressionOverrideOrDefault = resolutionContext.GetExpressionOverrideOrDefault(type, name);
if (expressionOverrideOrDefault != null)
return expressionOverrideOrDefault;
ServiceRegistration registrationOrDefault = resolutionContext.CurrentContainerContext.RegistrationRepository.GetRegistrationOrDefault(type, resolutionContext, name);
if (registrationOrDefault == null)
return BuildResolutionExpressionUsingResolvers(new TypeInformation(type, name), resolutionContext);
return expressionBuilder.BuildExpressionAndApplyLifetime(registrationOrDefault, resolutionContext, type);
}
public Expression BuildResolutionExpressionUsingResolvers(TypeInformation typeInfo, ResolutionContext resolutionContext)
{
Expression expression = resolverRepository.BuildResolutionExpression(typeInfo, resolutionContext, this);
if (expression != null)
return expression;
return lastChanceResolverRepository.BuildResolutionExpression(typeInfo, resolutionContext, this);
}
public bool CanResolveType(TypeInformation typeInfo, ResolutionContext resolutionContext)
{
if (!resolverRepository.CanResolve(typeInfo, resolutionContext))
return lastChanceResolverRepository.CanResolve(typeInfo, resolutionContext);
return true;
}
public void RegisterResolver(IResolver resolver)
{
Swap.SwapValue<IResolver, byte, byte, byte, ImmutableBucket<IResolver>>(ref resolverRepository, (IResolver t1, byte t2, byte t3, byte t4, ImmutableBucket<IResolver> repo) => repo.Add(t1), resolver, 0, 0, 0);
}
public void RegisterLastChanceResolver(IResolver resolver)
{
Swap.SwapValue<IResolver, byte, byte, byte, ImmutableBucket<IResolver>>(ref lastChanceResolverRepository, (IResolver t1, byte t2, byte t3, byte t4, ImmutableBucket<IResolver> repo) => repo.Add(t1), resolver, 0, 0, 0);
}
private IEnumerable<Expression> BuildAllResolverExpressionsUsingResolvers(TypeInformation typeInfo, ResolutionContext resolutionContext)
{
return resolverRepository.BuildAllResolutionExpressions(typeInfo, resolutionContext, this) ?? lastChanceResolverRepository.BuildAllResolutionExpressions(typeInfo, resolutionContext, this);
}
}
}