Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.1.0-preview-535" />

 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.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, typeInformation.DependencyName); 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.RequestInitiatorContainerContext ?? 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.RequestInitiatorContainerContext ?? 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); } } }