public override object Resolve() { if (ConstructorInfo == null) { throw new InvalidOperationException($"No constructor info for type {InterfaceType.FullName}"); } // If parameterless, create instance if (Parameters == null) { return(ConstructorInfo.Invoke(null)); } // If parameters, recursively create parameters instance object[] parameters = new object[Parameters.Count]; for (int i = 0; i < Parameters.Count; i++) { ResolveNodeBase unspecializedParameter = Parameters[i]; object parameterValue = unspecializedParameter.Resolve(); parameters[i] = parameterValue; } // and create instance using parameters return(ConstructorInfo.Invoke(parameters)); }
private ResolveNodeBase InnerBuildResolveTree(Type interfaceType, ICollection <Type> discoveredTypes, List <IParameterValue> userDefinedParameters = null) { // Factory ? Func <object> factory; if (_factories.TryGetValue(interfaceType, out factory)) { return new FactoryNode { InterfaceType = interfaceType, Factory = factory } } ; // Instance ? object instance; if (_instances.TryGetValue(interfaceType, out instance)) { return new InstanceNode { InterfaceType = interfaceType, Instance = instance } } ; // Implementation ? Type implementationType; if (!_implementations.TryGetValue(interfaceType, out implementationType)) { return(ErrorNode.TypeNotRegistered); } ConstructorInfo[] constructorInfos = implementationType.GetConstructors(); // Valid constructor ? if (constructorInfos.Length == 0 || (constructorInfos.Length == 1 && !constructorInfos[0].IsPublic)) { return(ErrorNode.NoPublicConstructorOrNoConstructor); } // Get parameters for each ctor var constructorAndParameters = constructorInfos.Select(x => new { Constructor = x, Parameters = x.GetParameters() }).ToList(); // Get first parameterless if any var parameterless = constructorAndParameters.FirstOrDefault(x => x.Parameters.Length == 0); if (parameterless != null) { return new BuildableNode { InterfaceType = interfaceType, ConstructorInfo = parameterless.Constructor } } ; // Check if every ctor's parameter is registered in container or resolvable, returns first resolvable foreach (var c in constructorAndParameters) { List <ResolveNodeBase> parametersResolvable = new List <ResolveNodeBase>(c.Parameters.Length); // Try to resolved every parameters bool ok = true; foreach (ParameterInfo parameterInfo in c.Parameters) { IParameterValue parameterValue = userDefinedParameters?.FirstOrDefault(x => x.Name == parameterInfo.Name); if (parameterValue != null) { ValueNode parameter = new ValueNode { InterfaceType = null, ParameterValue = parameterValue }; parametersResolvable.Add(parameter); } else { if (discoveredTypes.Any(x => x == parameterInfo.ParameterType)) // check cyclic dependency { ok = false; break; } discoveredTypes.Add(parameterInfo.ParameterType); // add parameter type to discovered type ResolveNodeBase parameter = InnerBuildResolveTree(parameterInfo.ParameterType, discoveredTypes, userDefinedParameters); discoveredTypes.Remove(parameterInfo.ParameterType); // remove parameter type from discovered type if (parameter is ErrorNode) // once an invalid ctor parameter has been found, try next ctor { ok = false; break; } parametersResolvable.Add(parameter); } } if (ok) { return new BuildableNode { InterfaceType = interfaceType, ConstructorInfo = c.Constructor, Parameters = parametersResolvable } } ; } return(ErrorNode.NoResolvableConstructor); } #endregion } }