public void GetTypeDifferenceWeightForZeroArgCtor() { int expectedWeight = 0; int actualWeight = AutowireUtils.GetTypeDifferenceWeight( ReflectionUtils.GetParameterTypes(typeof(Fable).GetConstructor(Type.EmptyTypes).GetParameters()), new object[] { }); Assert.AreEqual(expectedWeight, actualWeight, "AutowireUtils.GetTypeDifferenceWeight() was wrong, evidently."); }
public void GetTypeDifferenceWeightWithSameTypes() { int expectedWeight = 0; int actualWeight = AutowireUtils.GetTypeDifferenceWeight( ReflectionUtils.GetParameterTypes(typeof(Fool).GetConstructor(new Type[] { typeof(string) }).GetParameters()), new object[] { "Noob" }); Assert.AreEqual(expectedWeight, actualWeight, "AutowireUtils.GetTypeDifferenceWeight() was wrong, evidently."); }
public void GetTypeDifferenceWeightWhenPassingExactTypeMatch() { int expectedWeight = 0; int actualWeight = AutowireUtils.GetTypeDifferenceWeight( ReflectionUtils.GetParameterTypes(typeof(Fable).GetConstructor( new Type[] { typeof(EnglishCharacter) }).GetParameters()), new object[] { new EnglishCharacter() }); Assert.AreEqual(expectedWeight, actualWeight, "AutowireUtils.GetTypeDifferenceWeight() was wrong, evidently."); }
public void GetTypeDifferenceWeightWhenPassingDerivedTypeArgsToBaseTypeCtor() { int expectedWeight = 2; int actualWeight = AutowireUtils.GetTypeDifferenceWeight( ReflectionUtils.GetParameterTypes(typeof(Fable).GetConstructor( new Type[] { typeof(NurseryRhymeCharacter) }).GetParameters()), new object[] { new EnglishCharacter() }); Assert.AreEqual(expectedWeight, actualWeight, "AutowireUtils.GetTypeDifferenceWeight() was wrong, evidently."); }
public int GetTypeDifferenceWeight(Type[] paramTypes) { // If valid arguments found, determine type difference weight. // Try type difference weight on both the converted arguments and // the raw arguments. If the raw weight is better, use it. // Decrease raw weight by 1024 to prefer it over equal converted weight. int typeDiffWeight = AutowireUtils.GetTypeDifferenceWeight(paramTypes, this.arguments); int rawTypeDiffWeight = AutowireUtils.GetTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024; return(rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight); }
public void SortCtorsReallyIsGreedy() { BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; Type foolType = typeof(Fool); ConstructorInfo[] ctors = foolType.GetConstructors(flags); AutowireUtils.SortConstructors(ctors); ConstructorInfo[] expected = new ConstructorInfo[] { foolType.GetConstructor(new Type[] { typeof(string), typeof(int), typeof(Double), typeof(Fool) }), foolType.GetConstructor(new Type[] { typeof(string), typeof(int) }), foolType.GetConstructor(new Type[] { typeof(string) }), foolType.GetConstructor(Type.EmptyTypes), }; Assert.IsTrue(ArrayUtils.AreEqual(expected, ctors), "AutowireUtils.SortConstructors() did not put the greedy public ctors first."); }
// CLOVER:ON #endregion /// <summary> /// Gets those <see cref="System.Reflection.ConstructorInfo"/>s /// that are applicable for autowiring the supplied <paramref name="definition"/>. /// </summary> /// <param name="definition"> /// The <see cref="Oragon.Spring.Objects.Factory.Config.IObjectDefinition"/> /// (definition) that is being autowired by constructor. /// </param> /// <param name="minimumArgumentCount"> /// The absolute minimum number of arguments that any returned constructor /// must have. If this parameter is equal to zero (0), then all constructors /// are valid (regardless of their argument count), including any default /// constructor. /// </param> /// <returns> /// Those <see cref="System.Reflection.ConstructorInfo"/>s /// that are applicable for autowiring the supplied <paramref name="definition"/>. /// </returns> public static ConstructorInfo[] GetConstructors( IObjectDefinition definition, int minimumArgumentCount) { const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; ConstructorInfo[] constructors = null; if (minimumArgumentCount > 0) { MemberInfo[] ctors = definition.ObjectType.FindMembers( MemberTypes.Constructor, flags, new MemberFilter(new CriteriaMemberFilter().FilterMemberByCriteria), new MinimumArgumentCountCriteria(minimumArgumentCount)); constructors = (ConstructorInfo[])ArrayList.Adapter(ctors).ToArray(typeof(ConstructorInfo)); } else { constructors = definition.ObjectType.GetConstructors(flags); } AutowireUtils.SortConstructors(constructors); return(constructors); }
private static ConstructorInfo AssertTypeWeightingPicksCorrectCtor(object[] arguments, Type ctorType) { ConstructorInfo pickedCtor = null; // we want to pick the ctor that has the lowest type difference weight... ConstructorInfo[] ctors = ctorType.GetConstructors(); int weighting = Int32.MaxValue; foreach (ConstructorInfo ctor in ctors) { ParameterInfo[] parameters = ctor.GetParameters(); if (parameters.Length == arguments.Length) { Type[] paramTypes = ReflectionUtils.GetParameterTypes(parameters); int weight = AutowireUtils.GetTypeDifferenceWeight(paramTypes, arguments); if (weight < weighting) { pickedCtor = ctor; weighting = weight; } } } return(pickedCtor); }
/// <summary> /// Gets the constructor instantiation info given the object definition. /// </summary> /// <param name="objectName">Name of the object.</param> /// <param name="rod">The RootObjectDefinition</param> /// <param name="chosenCtors">The explicitly chosen ctors.</param> /// <param name="explicitArgs">The explicit chose ctor args.</param> /// <returns>A ConstructorInstantiationInfo containg the specified constructor in the RootObjectDefinition or /// one based on type matching.</returns> public ConstructorInstantiationInfo GetConstructorInstantiationInfo(string objectName, RootObjectDefinition rod, ConstructorInfo[] chosenCtors, object[] explicitArgs) { ObjectWrapper wrapper = new ObjectWrapper(); ConstructorInfo constructorToUse = null; object[] argsToUse = null; if (explicitArgs != null) { argsToUse = explicitArgs; } else { //TODO performance optmization on cached ctors. } // Need to resolve the constructor. bool autowiring = (chosenCtors != null || rod.ResolvedAutowireMode == AutoWiringMode.Constructor); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs = 0; if (explicitArgs != null) { minNrOfArgs = explicitArgs.Length; } else { ConstructorArgumentValues cargs = rod.ConstructorArgumentValues; resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = ResolveConstructorArguments(objectName, rod, wrapper, cargs, resolvedValues); } // Take specified constructors, if any. ConstructorInfo[] candidates = (chosenCtors != null ? chosenCtors : AutowireUtils.GetConstructors(rod, 0)); AutowireUtils.SortConstructors(candidates); int minTypeDiffWeight = Int32.MaxValue; for (int i = 0; i < candidates.Length; i++) { ConstructorInfo candidate = candidates[i]; Type[] paramTypes = ReflectionUtils.GetParameterTypes(candidate.GetParameters()); if (constructorToUse != null && argsToUse.Length > paramTypes.Length) { // already found greedy constructor that can be satisfied, so // don't look any further, there are only less greedy constructors left... break; } if (paramTypes.Length < minNrOfArgs) { throw new ObjectCreationException(rod.ResourceDescription, objectName, string.Format(CultureInfo.InvariantCulture, "'{0}' constructor arguments specified but no matching constructor found " + "in object '{1}' (hint: specify argument indexes, names, or " + "types to avoid ambiguities).", minNrOfArgs, objectName)); } ArgumentsHolder args = null; if (resolvedValues != null) { UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null; // Try to resolve arguments for current constructor //need to check for null as indicator of no ctor arg match instead of using exceptions for flow //control as in the Java implementation args = CreateArgumentArray(objectName, rod, resolvedValues, wrapper, paramTypes, candidate, autowiring, out unsatisfiedDependencyExceptionData); if (args == null) { if (i == candidates.Length - 1 && constructorToUse == null) { throw new UnsatisfiedDependencyException(rod.ResourceDescription, objectName, unsatisfiedDependencyExceptionData.ParameterIndex, unsatisfiedDependencyExceptionData.ParameterType, unsatisfiedDependencyExceptionData.ErrorMessage); } // try next constructor... continue; } } else { // Explicit arguments given -> arguments length must match exactly if (paramTypes.Length != explicitArgs.Length) { continue; } args = new ArgumentsHolder(explicitArgs); } int typeDiffWeight = args.GetTypeDifferenceWeight(paramTypes); // Choose this constructor if it represents the closest match. if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsToUse = args.arguments; minTypeDiffWeight = typeDiffWeight; } } if (constructorToUse == null) { throw new ObjectCreationException(rod.ResourceDescription, objectName, "Could not resolve matching constructor."); } return(new ConstructorInstantiationInfo(constructorToUse, argsToUse)); }
public void SortCtorsBailsSilentlyWhenGivenNull() { AutowireUtils.SortConstructors(null); }
public void GetTypeDifferenceWeightWithAllNulls() { Assert.Throws <NullReferenceException>(() => AutowireUtils.GetTypeDifferenceWeight(null, null)); }
public void GetTypeDifferenceWeightWithNullArgumentTypes() { Assert.Throws <NullReferenceException>(() => AutowireUtils.GetTypeDifferenceWeight(ReflectionUtils.GetParameterTypes(typeof(Fable).GetConstructor(new Type[] { typeof(FableCharacter) }).GetParameters()), null)); }
public void GetTypeDifferenceWeightWithNullParameterTypes() { Assert.Throws <NullReferenceException>(() => AutowireUtils.GetTypeDifferenceWeight(null, new object[] {})); }
public void GetTypeDifferenceWeightWithMismatchedLengths() { Assert.Throws <ArgumentException>(() => AutowireUtils.GetTypeDifferenceWeight(new Type[] {}, new object[] { 1 }), "Cannot calculate the type difference weight for argument types and arguments with differing lengths."); }