/// <summary> /// Gets the parameter list to call the given constructor. If a parameter could not be /// resolved, null is returned /// </summary> private async Task <object[]> GetParametersForAsync(ConstructorInfo constructor, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack) { Task <Object> WrapResult(object value) { return(Task.FromResult(value)); } // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local async Task <object> CreateInstance(Type parameterType, string parameterName) { object Instance = await componentContainer.InternalResolveInstanceAsync(parameterType, true, progressCallback, resolveStack); Instance.DbC_AssureNotNull($"Could not resolve component '{this.Descriptor.Type.FullName}' even though resolver claimed that he can. Parameter '{parameterName}' (type providing '{parameterType.FullName}' implementation) could not be instanciated"); return(Instance); } async Task <object> CreateInstances(Type parameterType, string parameterName) { Array Instance = await componentContainer.InternalResolveInstancesAsArrayAsync(parameterType.GetElementType(), progressCallback, resolveStack); return(Instance); } return(await Task.WhenAll(this.GetParametersFor(constructor, componentContainer, progressCallback, resolveStack, WrapResult, CreateInstance, CreateInstances))); }
private IEnumerable <T> GetParametersFor <T>(ConstructorInfo constructor, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack, Func <object, T> wrapResult, Func <Type, string, T> createInstance, Func <Type, string, T> createInstances ) { async Task <object> CreateInstanceArrayAsync(Type parameterType) { Array Instances = await componentContainer.InternalResolveInstancesAsArrayAsync(parameterType, progressCallback, resolveStack); return(Instances); } List <T> Parameters = new List <T>(); foreach (ParameterInfo Parameter in constructor.GetParameters()) { Type ParameterType = Parameter.ParameterType; if (ComponentInstance.IsValidInterfaceReference(ParameterType)) { T Component = createInstance(ParameterType, Parameter.Name); Parameters.Add(Component); } else if (ComponentInstance.IsValidInterfaceTaskReference(ParameterType)) { object Component = ComponentInstance.DoDynamicCastAsync(ParameterType, componentContainer.InternalResolveInstanceAsync(ParameterType.GenericTypeArguments[0], true, null, new ComponentDescriptor[0])); Parameters.Add(wrapResult(Component)); } else if (ComponentInstance.IsValidFuncToInterfaceReference(ParameterType)) { LambdaExpression Lambda = Expression.Lambda( ParameterType, Expression.Convert( ((Expression <Func <object> >)(() => componentContainer.InternalResolveInstance(ParameterType.GenericTypeArguments[0], true, progressCallback, new ComponentDescriptor[0]))).Body, ParameterType.GenericTypeArguments[0])); Parameters.Add(wrapResult(Lambda.Compile())); } else if (ComponentInstance.IsValidInterfaceArrayReference(ParameterType)) { Parameters.Add(createInstances(ParameterType, Parameter.Name)); } else if (ComponentInstance.IsValidInterfaceArrayTaskReference(ParameterType)) { object Component = ComponentInstance.DoDynamicCastAsync(ParameterType, CreateInstanceArrayAsync(ParameterType.GenericTypeArguments[0].GetElementType())); Parameters.Add(wrapResult(Component)); } else if (ComponentInstance.IsValidFuncToInterfaceArrayReference(ParameterType)) { LambdaExpression Lambda = Expression.Lambda( ParameterType, Expression.Convert( ((Expression <Func <Array> >)(() => componentContainer.InternalResolveInstancesAsArray(ParameterType.GenericTypeArguments[0].GetElementType(), progressCallback, new ComponentDescriptor[0]))).Body, ParameterType.GenericTypeArguments[0])); Parameters.Add(wrapResult(Lambda.Compile())); } else if (ParameterType == typeof(ComponentRepository)) { Parameters.Add(wrapResult(this.Descriptor.PrivateRepository ?? this.Descriptor.Repository)); } else if (ParameterType == typeof(ComponentContainer)) { Parameters.Add(wrapResult(componentContainer)); } else if (ParameterType.IsAssignableFrom(this.Descriptor.ConfigType)) { Parameters.Add(wrapResult(this.Descriptor.Config)); } else { throw new InvalidOperationException("Internal error: tried to resolve constructor parameters even though the constructor wasn't adequate"); } } return(Parameters); }