/// <summary> /// Create an array of arguments to invoke a constructor or static factory method, /// given the resolved constructor arguments values. /// </summary> /// <remarks>When return value is null the out parameter UnsatisfiedDependencyExceptionData will contain /// information for use in throwing a UnsatisfiedDependencyException by the caller. This avoids using /// exceptions for flow control as in the original implementation.</remarks> private ArgumentsHolder CreateArgumentArray(string objectName, RootObjectDefinition rod, ConstructorArgumentValues resolvedValues, ObjectWrapper wrapper, Type[] paramTypes, MethodBase methodOrCtorInfo, bool autowiring, out UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData) { string methodType = (methodOrCtorInfo is ConstructorInfo) ? "constructor" : "factory method"; unsatisfiedDependencyExceptionData = null; ArgumentsHolder args = new ArgumentsHolder(paramTypes.Length); ISet usedValueHolders = new HybridSet(); IList autowiredObjectNames = new LinkedList(); bool resolveNecessary = false; ParameterInfo[] argTypes = methodOrCtorInfo.GetParameters(); for (int paramIndex = 0; paramIndex < paramTypes.Length; paramIndex++) { Type paramType = paramTypes[paramIndex]; string parameterName = argTypes[paramIndex].Name; // If we couldn't find a direct match and are not supposed to autowire, // let's try the next generic, untyped argument value as fallback: // it could match after type conversion (for example, String -> int). ConstructorArgumentValues.ValueHolder valueHolder = null; if (resolvedValues.GetNamedArgumentValue(parameterName) != null) { valueHolder = resolvedValues.GetArgumentValue(parameterName, paramType, usedValueHolders); } else { valueHolder = resolvedValues.GetArgumentValue(paramIndex, paramType, usedValueHolders); } if (valueHolder == null && !autowiring) { valueHolder = resolvedValues.GetGenericArgumentValue(null, usedValueHolders); } if (valueHolder != null) { // We found a potential match - let's give it a try. // Do not consider the same value definition multiple times! usedValueHolders.Add(valueHolder); args.rawArguments[paramIndex] = valueHolder.Value; try { object originalValue = valueHolder.Value; object convertedValue = TypeConversionUtils.ConvertValueIfNecessary(paramType, originalValue, null); args.arguments[paramIndex] = convertedValue; //? args.preparedArguments[paramIndex] = convertedValue; } catch (TypeMismatchException ex) { //To avoid using exceptions for flow control, this is not a cost in Java as stack trace is lazily created. string errorMessage = String.Format(CultureInfo.InvariantCulture, "Could not convert {0} argument value [{1}] to required type [{2}] : {3}", methodType, valueHolder.Value, paramType, ex.Message); unsatisfiedDependencyExceptionData = new UnsatisfiedDependencyExceptionData(paramIndex, paramType, errorMessage); return(null); } } else { // No explicit match found: we're either supposed to autowire or // have to fail creating an argument array for the given constructor. if (!autowiring) { string errorMessage = String.Format(CultureInfo.InvariantCulture, "Ambiguous {0} argument types - " + "Did you specify the correct object references as {0} arguments?", methodType); unsatisfiedDependencyExceptionData = new UnsatisfiedDependencyExceptionData(paramIndex, paramType, errorMessage); return(null); } try { MethodParameter param = MethodParameter.ForMethodOrConstructor(methodOrCtorInfo, paramIndex); object autowiredArgument = ResolveAutoWiredArgument(param, objectName, autowiredObjectNames); args.rawArguments[paramIndex] = autowiredArgument; args.arguments[paramIndex] = autowiredArgument; args.preparedArguments[paramIndex] = new AutowiredArgumentMarker(); resolveNecessary = true; } catch (ObjectsException ex) { unsatisfiedDependencyExceptionData = new UnsatisfiedDependencyExceptionData(paramIndex, paramType, ex.Message); return(null); } } } foreach (string autowiredObjectName in autowiredObjectNames) { if (log.IsDebugEnabled) { log.Debug("Autowiring by type from object name '" + objectName + "' via " + methodType + " to object named '" + autowiredObjectName + "'"); } } return(args); }