ResolutionStrategy
using Stashbox.Entity;
using Stashbox.Registration;
using Stashbox.Resolution.Resolvers;
using Stashbox.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Stashbox.Resolution
{
internal class ResolutionStrategy : IResolverSupportedResolutionStrategy, IResolutionStrategy
{
private ImmutableArray<IMultiServiceResolver> multiServiceResolverRepository = ImmutableArray<IMultiServiceResolver>.Empty;
private ImmutableArray<IResolver> resolverRepository = ImmutableArray<IResolver>.Empty;
private readonly UnknownTypeResolver unknownTypeResolver = new UnknownTypeResolver();
private readonly ParentContainerResolver parentContainerResolver = new ParentContainerResolver();
public Expression BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, IEnumerable<InjectionParameter> injectionParameters = null, bool forceSkipUnknownTypeCheck = false)
{
if ((object)typeInformation.Type == Constants.ResolverType)
return resolutionContext.CurrentScopeParameter.ConvertTo(Constants.ResolverType);
if (resolutionContext.ResolutionScope.HasScopedInstances && resolutionContext.ResolutionScope.GetScopedInstanceOrDefault(typeInformation.Type, typeInformation.DependencyName) != null)
return resolutionContext.CurrentScopeParameter.CallMethod(Constants.GetScopedInstanceMethod, typeInformation.Type.AsConstant(), typeInformation.DependencyName.AsConstant()).ConvertTo(typeInformation.Type);
if (resolutionContext.ParameterExpressions.Count > 0) {
int num = resolutionContext.ParameterExpressions.Count;
while (num-- > 0) {
KeyValue<bool, ParameterExpression>[] array = resolutionContext.ParameterExpressions[num].WhereOrDefault(delegate(KeyValue<bool, ParameterExpression> p) {
if ((object)p.Value.Type != typeInformation.Type)
return p.Value.Type.Implements(typeInformation.Type);
return true;
});
if (array != null) {
KeyValue<bool, ParameterExpression> obj = array.FirstOrDefault((KeyValue<bool, ParameterExpression> parameter) => !parameter.Key) ?? array.Last();
obj.Key = true;
return obj.Value;
}
}
}
InjectionParameter injectionParameter = (injectionParameters != null) ? injectionParameters.FirstOrDefault((InjectionParameter param) => param.Name == typeInformation.ParameterOrMemberName) : null;
if (injectionParameter != null) {
if (injectionParameter.Value == null) {
if ((object)typeInformation.Type != Constants.ObjectType)
return injectionParameter.Value.AsConstant().ConvertTo(typeInformation.Type);
return injectionParameter.Value.AsConstant();
}
if ((object)injectionParameter.Value.GetType() != typeInformation.Type)
return injectionParameter.Value.AsConstant().ConvertTo(typeInformation.Type);
return injectionParameter.Value.AsConstant();
}
Expression expressionOverrideOrDefault = resolutionContext.GetExpressionOverrideOrDefault(typeInformation.Type);
if (expressionOverrideOrDefault != null)
return expressionOverrideOrDefault;
IServiceRegistration registrationOrDefault = containerContext.RegistrationRepository.GetRegistrationOrDefault(typeInformation, resolutionContext);
if (registrationOrDefault == null)
return BuildResolutionExpressionUsingResolvers(containerContext, typeInformation, resolutionContext, forceSkipUnknownTypeCheck);
return registrationOrDefault.GetExpression(resolutionContext.ChildContext ?? containerContext, resolutionContext, typeInformation.Type);
}
public Expression[] BuildAllResolutionExpressions(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation)
{
IEnumerable<IServiceRegistration> registrationsOrDefault = containerContext.RegistrationRepository.GetRegistrationsOrDefault(typeInformation, resolutionContext);
IServiceRegistration[] array = (registrationsOrDefault != null) ? registrationsOrDefault.CastToArray() : null;
if (array == null)
return BuildAllResolverExpressionsUsingResolvers(containerContext, typeInformation, resolutionContext);
int num = array.Length;
Expression[] array2 = new Expression[num];
for (int i = 0; i < num; i++) {
array2[i] = array[i].GetExpression(resolutionContext.ChildContext ?? containerContext, resolutionContext, typeInformation.Type);
}
return array2;
}
public Expression BuildResolutionExpressionUsingResolvers(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext, bool forceSkipUnknownTypeCheck = false)
{
for (int i = 0; i < resolverRepository.Length; i++) {
IResolver resolver = resolverRepository.Get(i);
if (resolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return resolver.GetExpression(containerContext, this, typeInfo, resolutionContext);
}
if (parentContainerResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return parentContainerResolver.GetExpression(containerContext, this, typeInfo, resolutionContext);
if (forceSkipUnknownTypeCheck || !unknownTypeResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return null;
return unknownTypeResolver.GetExpression(containerContext, this, typeInfo, resolutionContext);
}
public bool CanResolveType(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext)
{
for (int i = 0; i < resolverRepository.Length; i++) {
if (resolverRepository.Get(i).CanUseForResolution(containerContext, typeInfo, resolutionContext))
return true;
}
if (!parentContainerResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return unknownTypeResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext);
return true;
}
public void RegisterResolver(IResolver resolver)
{
Swap.SwapValue<IResolver, byte, byte, byte, ImmutableArray<IResolver>>(ref resolverRepository, (IResolver t1, byte t2, byte t3, byte t4, ImmutableArray<IResolver> repo) => repo.Add(t1), resolver, 0, 0, 0);
IMultiServiceResolver multiServiceResolver = resolver as IMultiServiceResolver;
if (multiServiceResolver != null)
Swap.SwapValue<IMultiServiceResolver, byte, byte, byte, ImmutableArray<IMultiServiceResolver>>(ref multiServiceResolverRepository, (IMultiServiceResolver t1, byte t2, byte t3, byte t4, ImmutableArray<IMultiServiceResolver> repo) => repo.Add(t1), multiServiceResolver, 0, 0, 0);
}
private Expression[] BuildAllResolverExpressionsUsingResolvers(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext)
{
for (int i = 0; i < multiServiceResolverRepository.Length; i++) {
IMultiServiceResolver multiServiceResolver = multiServiceResolverRepository.Get(i);
if (multiServiceResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return multiServiceResolver.GetAllExpressions(containerContext, this, typeInfo, resolutionContext);
}
if (!parentContainerResolver.CanUseForResolution(containerContext, typeInfo, resolutionContext))
return null;
return parentContainerResolver.GetAllExpressions(containerContext, this, typeInfo, resolutionContext);
}
}
}