Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.1.1-preview-550" />

 MethodExpressionFactory

using Stashbox.Exceptions; using Stashbox.Registration; using Stashbox.Resolution; using Stashbox.Resolution.Extensions; using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Text; namespace Stashbox.Expressions { internal class MethodExpressionFactory { public IEnumerable<Expression> CreateParameterExpressionsForMethod(RegistrationContext registrationContext, ResolutionContext resolutionContext, MethodBase method) { ParameterInfo[] parameters = method.GetParameters(); int paramLength = parameters.Length; int i = 0; TypeInformation parameter; while (true) { if (i >= paramLength) yield break; parameter = parameters[i].AsTypeInformation(method.DeclaringType, registrationContext, resolutionContext.CurrentContainerContext.ContainerConfiguration); Expression expression = registrationContext.InjectionParameters.SelectInjectionParameterOrDefault(parameter); if (expression != null) yield return expression; Expression expression2 = resolutionContext.ResolutionStrategy.BuildExpressionForType(resolutionContext, parameter); if (expression2 == null) break; yield return expression2; i++; } throw new ResolutionFailedException(method.DeclaringType, $"""{method}""{parameter.Type}""{parameter.ParameterOrMemberName}", null); } public ConstructorInfo SelectConstructor(RegistrationContext registrationContext, ResolutionContext resolutionContext, ConstructorInfo[] constructors, out Expression[] parameterExpressions) { Dictionary<MethodBase, TypeInformation> dictionary = new Dictionary<MethodBase, TypeInformation>(); ResolutionContext resolutionContext2 = resolutionContext.CurrentContainerContext.ContainerConfiguration.UnknownTypeResolutionEnabled ? resolutionContext.BeginUnknownTypeCheckDisabledContext() : resolutionContext; int num = constructors.Length; for (int i = 0; i < num; i++) { ConstructorInfo constructorInfo = constructors[i]; if (TryBuildMethod(constructorInfo, registrationContext, resolutionContext2, out TypeInformation failedParameter, out parameterExpressions)) return constructorInfo; dictionary.Add(constructorInfo, failedParameter); } if (resolutionContext.CurrentContainerContext.ContainerConfiguration.UnknownTypeResolutionEnabled) { for (int j = 0; j < num; j++) { ConstructorInfo constructorInfo2 = constructors[j]; if (TryBuildMethod(constructorInfo2, registrationContext, resolutionContext, out TypeInformation _, out parameterExpressions)) return constructorInfo2; } } if (resolutionContext.NullResultAllowed) { parameterExpressions = null; return null; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair<MethodBase, TypeInformation> item in dictionary) { stringBuilder.AppendLine($"""{item.Key}""{item.Value.Type.FullName}""{item.Value.ParameterOrMemberName}"""); } throw new ResolutionFailedException(constructors[0].DeclaringType, stringBuilder.ToString(), null); } public IEnumerable<Expression> CreateMethodExpressions(IEnumerable<MethodInfo> methods, RegistrationContext registrationContext, ResolutionContext resolutionContext, Expression instance) { foreach (MethodInfo method in methods) { if (method.GetParameters().Length == 0) yield return (Expression)instance.CallMethod(method, Array.Empty<Expression>()); else yield return (Expression)instance.CallMethod(method, CreateParameterExpressionsForMethod(registrationContext, resolutionContext, method)); } } private bool TryBuildMethod(MethodBase method, RegistrationContext registrationContext, ResolutionContext resolutionContext, out TypeInformation failedParameter, out Expression[] parameterExpressions) { ParameterInfo[] parameters = method.GetParameters(); int num = parameters.Length; parameterExpressions = new Expression[num]; failedParameter = null; for (int i = 0; i < num; i++) { TypeInformation typeInformation = parameters[i].AsTypeInformation(method.DeclaringType, registrationContext, resolutionContext.CurrentContainerContext.ContainerConfiguration); Expression expression = registrationContext.InjectionParameters.SelectInjectionParameterOrDefault(typeInformation); parameterExpressions[i] = (expression ?? resolutionContext.ResolutionStrategy.BuildExpressionForType(resolutionContext, typeInformation)); if (parameterExpressions[i] == null) { failedParameter = typeInformation; return false; } } return true; } } }