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 ArrayStore<IMultiServiceResolver> multiServiceResolverRepository = ArrayStore<IMultiServiceResolver>.Empty;
private ArrayStore<IResolver> resolverRepository = ArrayStore<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.Length > 0) {
int num = resolutionContext.ParameterExpressions.Length;
while (num-- > 0) {
ArrayStoreKeyed<bool, ParameterExpression> arrayStoreKeyed = 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 (arrayStoreKeyed != null) {
KeyValue<bool, ParameterExpression> obj = arrayStoreKeyed.Repository.FirstOrDefault((KeyValue<bool, ParameterExpression> parameter) => !parameter.Key) ?? arrayStoreKeyed.Repository.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<KeyValue<object, IServiceRegistration>> registrationsOrDefault = containerContext.RegistrationRepository.GetRegistrationsOrDefault(typeInformation, resolutionContext);
KeyValue<object, 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].Value.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, ArrayStore<IResolver>>(ref resolverRepository, (IResolver t1, byte t2, byte t3, byte t4, ArrayStore<IResolver> repo) => repo.Add(t1), resolver, 0, 0, 0);
IMultiServiceResolver multiServiceResolver = resolver as IMultiServiceResolver;
if (multiServiceResolver != null)
Swap.SwapValue<IMultiServiceResolver, byte, byte, byte, ArrayStore<IMultiServiceResolver>>(ref multiServiceResolverRepository, (IMultiServiceResolver t1, byte t2, byte t3, byte t4, ArrayStore<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);
}
}
}