MethodExpressionFactory
class 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;
}
}
}