/// <summary> /// Creates a instance of the given <see cref="type"/> /// </summary> /// <param name="type"> /// The dictionaryType to create /// </param> /// <param name="currentSetupItem"> /// The setup for the current object dictionaryType /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> /// <returns> /// Created instance of the given <see cref="Type"/> /// </returns> /// <exception cref="InvalidOperationException"> /// Throws exception if the constructor could not be created by filler setup /// </exception> private object CreateInstanceOfType(Type type, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { var constructorArgs = new List <object>(); if (type.GetConstructors().All(ctor => ctor.GetParameters().Length != 0)) { IEnumerable <ConstructorInfo> ctorInfos; if ((ctorInfos = type.GetConstructors().Where(ctr => ctr.GetParameters().Length != 0)).Any()) { foreach (ConstructorInfo ctorInfo in ctorInfos.OrderBy(x => x.GetParameters().Length)) { Type[] paramTypes = ctorInfo.GetParameters().Select(p => p.ParameterType).ToArray(); if (paramTypes.All(ctorParamType => TypeIsValidForObjectFiller(ctorParamType, currentSetupItem) && ctorParamType != type)) { foreach (Type paramType in paramTypes) { constructorArgs.Add(this.CreateAndFillObject(paramType, currentSetupItem, typeTracker)); } break; } } if (constructorArgs.Count == 0) { var message = "Could not found a constructor for type [" + type.Name + "] where the parameters can be filled with the current objectfiller setup"; throw new InvalidOperationException(message); } } } object result = Activator.CreateInstance(type, constructorArgs.ToArray()); return(result); }
/// <summary> /// Creates and fills a list of the given <see cref="propertyType"/> /// </summary> /// <param name="propertyType"> /// Type of the list /// </param> /// <param name="currentSetupItem"> /// The current setup item. /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> /// <returns> /// Created and filled list of the given <see cref="propertyType"/> /// </returns> private IList GetFilledList(Type propertyType, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { Type genType = propertyType.GetGenericTypeArguments()[0]; if (this.CheckForCircularReference(genType, typeTracker, currentSetupItem)) { return(null); } IList list; if (!propertyType.IsInterface() && propertyType.GetImplementedInterfaces().Any(x => x == typeof(IList))) { list = (IList)Activator.CreateInstance(propertyType); } else if (propertyType.IsGenericType() && propertyType.GetGenericTypeDefinition() == typeof(IEnumerable <>) || propertyType.GetImplementedInterfaces().Any(x => x.GetGenericTypeDefinition() == typeof(IEnumerable <>))) { Type openListType = typeof(List <>); Type genericListType = openListType.MakeGenericType(genType); list = (IList)Activator.CreateInstance(genericListType); } else { list = (IList)Activator.CreateInstance(propertyType); } int maxListItems = Random.Next(currentSetupItem.ListMinCount, currentSetupItem.ListMaxCount); for (int i = 0; i < maxListItems; i++) { object listObject = this.CreateAndFillObject(genType, currentSetupItem, typeTracker); list.Add(listObject); } return(list); }
/// <summary> /// Creates and fills a list of the given <see cref="propertyType"/> /// </summary> /// <param name="propertyType"> /// Type of the list /// </param> /// <param name="currentSetupItem"> /// The current setup item. /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> /// <returns> /// Created and filled list of the given <see cref="propertyType"/> /// </returns> private IEnumerable GetFilledCollection(Type propertyType, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { Type genType = propertyType.GetGenericTypeArguments()[0]; if (this.CheckForCircularReference(genType, typeTracker, currentSetupItem)) { return(null); } IEnumerable target; if (!propertyType.IsInterface() && propertyType.GetImplementedInterfaces().Any(x => x.GetGenericTypeDefinition() == typeof(ICollection <>))) { target = (IEnumerable)Activator.CreateInstance(propertyType); } else if (propertyType.IsGenericType() && propertyType.GetGenericTypeDefinition() == typeof(ICollection <>) || propertyType.GetImplementedInterfaces().Any(x => x.GetGenericTypeDefinition() == typeof(ICollection <>))) { Type openListType = typeof(List <>); Type genericListType = openListType.MakeGenericType(genType); target = (IEnumerable)Activator.CreateInstance(genericListType); } else { target = (IEnumerable)Activator.CreateInstance(propertyType); } int maxListItems = Random.Next(currentSetupItem.ListMinCount, currentSetupItem.ListMaxCount); for (int i = 0; i < maxListItems; i++) { object listObject = this.CreateAndFillObject(genType, currentSetupItem, typeTracker); MethodInfo method = target.GetType().GetMethod("Add"); method.Invoke(target, new object[] { listObject }); } return(target); }
/// <summary> /// Creates and fills a list of the given <see cref="propertyType"/> /// </summary> /// <param name="propertyType"> /// Type of the list /// </param> /// <param name="currentSetupItem"> /// The current setup item. /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> /// <returns> /// Created and filled list of the given <see cref="propertyType"/> /// </returns> private IList GetFilledList(Type propertyType, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { bool derivedList = !propertyType.GetGenericTypeArguments().Any(); Type genType = !derivedList?propertyType.GetGenericTypeArguments()[0] : propertyType.GetTypeInfo().BaseType.GetGenericTypeArguments()[0]; if (this.CheckForCircularReference(genType, typeTracker, currentSetupItem)) { return(null); } IList list; if (!propertyType.IsInterface() && propertyType.GetImplementedInterfaces().Any(x => x == typeof(IList))) { list = (IList)Activator.CreateInstance(propertyType); } else if (propertyType.IsGenericType() && propertyType.GetGenericTypeDefinition() == typeof(IEnumerable <>) || propertyType.GetImplementedInterfaces().Any(x => x.GetGenericTypeDefinition() == typeof(IEnumerable <>))) { Type openListType = typeof(List <>); Type genericListType = openListType.MakeGenericType(genType); list = (IList)Activator.CreateInstance(genericListType); } else { list = (IList)Activator.CreateInstance(propertyType); } int maxListItems = Random.Next(currentSetupItem.ListMinCount, currentSetupItem.ListMaxCount); for (int i = 0; i < maxListItems; i++) { object listObject = this.CreateAndFillObject(genType, currentSetupItem, typeTracker); list.Add(listObject); } if (derivedList) { var remainingProperties = propertyType.GetProperties(true) .Where(prop => this.GetSetMethodOnDeclaringType(prop) != null) .ToArray(); this.FillProperties(list, remainingProperties, currentSetupItem, typeTracker); } return(list); }
/// <summary> /// Creates and fills a dictionary of the target <see cref="propertyType"/> /// </summary> /// <param name="propertyType"> /// The dictionaryType of the dictionary /// </param> /// <param name="currentSetupItem"> /// The current setup item. /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> /// <returns> /// A created and filled dictionary /// </returns> /// <exception cref="ArgumentException"> /// Throws exception if the setup was made in a way that the keys of the dictionary are always the same /// </exception> private IDictionary GetFilledDictionary( Type propertyType, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { IDictionary dictionary = (IDictionary)Activator.CreateInstance(propertyType); bool derivedType = !propertyType.GetGenericTypeArguments().Any(); Type keyType = !derivedType ? propertyType.GetGenericTypeArguments()[0] : propertyType.GetTypeInfo().BaseType.GetGenericTypeArguments()[0]; Type valueType = !derivedType ? propertyType.GetGenericTypeArguments()[1] : propertyType.GetTypeInfo().BaseType.GetGenericTypeArguments()[1]; int maxDictionaryItems = 0; if (keyType.IsEnum()) { maxDictionaryItems = Enum.GetValues(keyType).Length; } else { maxDictionaryItems = Random.Next( currentSetupItem.DictionaryKeyMinCount, currentSetupItem.DictionaryKeyMaxCount); } for (int i = 0; i < maxDictionaryItems; i++) { object keyObject = null; if (keyType.IsEnum()) { keyObject = Enum.GetValues(keyType).GetValue(i); } else { keyObject = this.CreateAndFillObject(keyType, currentSetupItem, typeTracker); } if (dictionary.Contains(keyObject)) { string message = string.Format( "Generating Keyvalue failed because it generates always the same data for dictionaryType [{0}]. Please check your setup.", keyType); throw new ArgumentException(message); } object valueObject = this.CreateAndFillObject(valueType, currentSetupItem, typeTracker); dictionary.Add(keyObject, valueObject); } if (derivedType) { var remainingProperties = propertyType.GetProperties(true) .Where(prop => this.GetSetMethodOnDeclaringType(prop) != null) .ToArray(); this.FillProperties(dictionary, remainingProperties, currentSetupItem, typeTracker); } return(dictionary); }
/// <summary> /// This method will fill the given <see cref="properties"/> of the given <see cref="objectToFill"/> /// </summary> /// <param name="objectToFill">The object to fill</param> /// <param name="properties">The properties of the <see cref="objectToFill"/> which shall get filled</param> /// <param name="currentSetup"> /// The setup for the current object /// </param> /// <param name="typeTracker"> /// The dictionaryType tracker to find circular dependencies /// </param> private void FillProperties(object objectToFill, PropertyInfo[] properties, FillerSetupItem currentSetup, HashStack <Type> typeTracker) { if (properties.Length == 0) { return; } Queue <PropertyInfo> orderedProperties = this.OrderPropertiers(currentSetup, properties); while (orderedProperties.Count != 0) { PropertyInfo property = orderedProperties.Dequeue(); if (currentSetup.TypesToIgnore.Contains(property.PropertyType)) { continue; } if (this.IgnoreProperty(property, currentSetup)) { continue; } if (this.ContainsProperty(currentSetup.PropertyToRandomFunc.Keys, property)) { PropertyInfo propertyInfo = this.GetPropertyFromProperties(currentSetup.PropertyToRandomFunc.Keys, property).Single(); this.SetPropertyValue(property, objectToFill, currentSetup.PropertyToRandomFunc[propertyInfo]()); continue; } if (this.justConfiguredProperties && !this.setupManager.FillerSetup.TypeToFillerSetup.ContainsKey(property.PropertyType)) { continue; } object filledObject = this.CreateAndFillObject(property.PropertyType, currentSetup, typeTracker); this.SetPropertyValue(property, objectToFill, filledObject); } }
/// <summary> /// Generates keys for a randomized dictionary. If <paramref name="keyType"/> is an enumeration, special /// handling is taken to ensure that duplicates aren't created. /// </summary> /// <param name="keyType">The dictionary key type</param> /// <param name="currentSetupItem">The current setup item</param> /// <param name="typeTracker">The dictionaryType tracker to find circular dependencies</param> /// <returns></returns> private List <object> GenerateDictionaryKeys(Type keyType, FillerSetupItem currentSetupItem, HashStack <Type> typeTracker) { List <object> keys = new List <object>(); if (keyType.IsEnum) { // TODO: The result of this could be cached for performance if desired var enumValues = Enum.GetValues(keyType).Cast <object>().ToList(); int maxDictionaryItems = Random.Next( Math.Min(enumValues.Count, currentSetupItem.DictionaryKeyMinCount), Math.Min(enumValues.Count, currentSetupItem.DictionaryKeyMaxCount)); for (int i = 0; i < maxDictionaryItems; i++) { int randomIndex = Random.Next(enumValues.Count); var key = enumValues[randomIndex]; keys.Add(key); enumValues.Remove(key); } } else { int maxDictionaryItems = Random.Next( currentSetupItem.DictionaryKeyMinCount, currentSetupItem.DictionaryKeyMaxCount); for (int i = 0; i < maxDictionaryItems; i++) { keys.Add(this.CreateAndFillObject(keyType, currentSetupItem, typeTracker)); } } return(keys); }