/// <summary> /// Sets all members of the given member. /// </summary> /// <typeparam name="T">The type to create an instance of.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The current member.</param> private static void SetAllMembers <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { // Check if children should be set or not if (!IncludeChildMembers(options, memberInformation)) { return; } // Get the properties of the current member as member information var propertyInfos = memberInformation.MemberType.GetPublicSettableProperties() .GetMemberInformation(memberInformation); propertyInfos.ForEach(x => { // Check if member should be set or not if (!IncludeMember(options, x)) { return; } // Create member value var value = GetValue(options, x); x.PropertyInfo.SetValue(memberInformation.MemberObject, value, null); // Set children of value (recursive call) var currentMember = x as MemberInformation; if (currentMember != null) { currentMember.MemberObject = value; } SetAllMembers(options, currentMember); }); }
/// <summary> /// Tries to create an array value for the given type. /// </summary> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <returns>Returns the created value, or null if the given type is not an array type.</returns> private static Object TryCreateArrayValue <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { // Check if member is an array type if (!memberInformation.MemberType.IsArray) { return(null); } // Create the array var elementType = memberInformation.MemberType.GetElementType(); var array = Array.CreateInstance(elementType, GetCollectionItemCount(options)); // Add items var anonymousItemName = GetAnonymousItemName(options); for (var i = 0; i < array.Length; i++) { var currentMember = new MemberInformation { MemberType = elementType, MemberPath = $"{memberInformation.MemberPath}.{anonymousItemName}", MemberName = anonymousItemName }; // Get the value of the current array item. var arrayItemValue = GetValue(options, currentMember); currentMember.MemberObject = arrayItemValue; SetAllMembers(options, currentMember); array.SetValue(arrayItemValue, i); } return(array); }
/// <summary> /// Gets the matching factory for the given member. /// </summary> /// <exception cref="CreateInstanceException">Multiple matching factories found.</exception> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <returns>Returns the matching factory, or null if no factory was found.</returns> private static IInstanceFactory GetFactory <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { // Get matching factory var factory = GetExactlymatchingFactory(options, memberInformation); if (factory != null) { return(factory); } // Try get inner type of null-able var nullableType = memberInformation.MemberType.GetTypeFromNullable(); if (nullableType == null) { return(null); } // Update type if (memberInformation is MemberInformation info) { info.MemberType = nullableType; } return(GetExactlymatchingFactory(options, memberInformation)); }
/// <summary> /// Populates the given instance if it is a collection, based on the collection configuration. /// </summary> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <param name="collectionInstance">The instance to populate.</param> /// <returns>Returns the populated or unmodified instance.</returns> private static Object TryPopulateCollection <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation, Object collectionInstance) where T : class { // Check if collection should get populated or not if (!PopulateCollection(options) || collectionInstance == null) { return(collectionInstance); } // Check if type is collection type if (!memberInformation.MemberType.ImplementsICollectionT()) { return(collectionInstance); } // Get generic parameter type var genericArgumentTypes = memberInformation .MemberType .GetGenericTypeArguments() .ToArray(); // Get the add method var addMethod = memberInformation.MemberType .GetRuntimeMethod("Add", genericArgumentTypes); // Add items var anonymousItemName = GetAnonymousItemName(options); var collectionCount = GetCollectionItemCount(options); for (var i = 0; i < collectionCount; i++) { var addParameters = new List <Object>(); genericArgumentTypes .ForEach(x => { var currentMember = new MemberInformation { MemberType = x, MemberPath = $"{memberInformation.MemberPath}.{anonymousItemName}", MemberName = anonymousItemName }; // Get the value for the current collection item. var collectionItemValue = GetValue(options, currentMember); currentMember.MemberObject = collectionItemValue; SetAllMembers(options, currentMember); addParameters.Add(collectionItemValue); }); addMethod.Invoke(collectionInstance, addParameters.ToArray()); } return(collectionInstance); }
/// <summary> /// Gets the number of items to create for a collection. /// </summary> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <returns>Returns the number of items to create.</returns> private static Int32 GetCollectionItemCount <T>(ICreateInstanceOptionsComplete <T> options) where T : class { //Return count of 0 if collection should net get populated if (!PopulateCollection(options)) { return(0); } var min = options.PopulateCollectionsMinCount ?? PopulateCollectionsMinCount; var max = options.PopulateCollectionsMaxCount ?? PopulateCollectionsMaxCount; return(RandomValueEx.GetRandomInt32(min, max)); }
/// <summary> /// Gets a value for the given member. /// </summary> /// <exception cref="CreateInstanceException">Value creation failed.</exception> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <returns>Returns the created value.</returns> private static Object GetValue <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { // Try get value from factory var factory = GetFactory(options, memberInformation); if (factory != null) { try { return(factory.CreateValue(memberInformation)); } catch (Exception ex) { throw new CreateInstanceException("Factory has thrown exception.", ex, factory.ToString(), null, memberInformation); } } // Try create array value var value = TryCreateArrayValue(options, memberInformation); if (value != null) { return(value); } // Create value (first try IEnumerable than anything else) value = TryCreateCollectionValue(memberInformation); // ReSharper disable once InvertIf if (value == null) { try { value = CreateValueUsingAcrivator(memberInformation); } catch (Exception ex) { throw new CreateInstanceException($"Failed to create instance due to missing or invalid factory for type '{memberInformation.MemberType}'.", ex, null, null, memberInformation); } } // Populate collection if collection (could be ICollection) return(TryPopulateCollection(options, memberInformation, value)); }
/// <summary> /// Creates the root instance. /// </summary> /// <exception cref="CreateInstanceException">Value creation failed.</exception> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to create.</param> /// <returns>Returns the created value.</returns> private static T CreateRootMember <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { try { var value = GetValue(options, memberInformation); return((T)value); } catch (Exception ex) { throw new CreateInstanceException($"Failed to create root object of type: {typeof(T).Name}.", ex, options.Factories.Concat(DefaultFactories) .StringJoin(Environment.NewLine), null, memberInformation); } }
/// <summary> /// Gets the matching factory for the given member. /// </summary> /// <exception cref="CreateInstanceException">Multiple matching factories found.</exception> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <returns>Returns the matching factory, or null if no factory was found.</returns> private static IInstanceFactory GetExactlymatchingFactory <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) where T : class { // Get factory from options var matchingFactories = options.Factories.Where(x => RuleInspector.Inspect(x.SelectionRules, memberInformation) == MemberSelectionResult.IncludeMember) .ToList(); if (matchingFactories.Count == 1) { return(matchingFactories.Single()); } // Check if multiple factories have matched if (matchingFactories.Any()) { throw new CreateInstanceException( $"Found multiple matching factories for member (in options). Type is '{memberInformation.MemberType}'. Please make sure only one factory matches the member.", null, options.Factories.StringJoin(Environment.NewLine), null, memberInformation); } // Get factory from default factories matchingFactories = DefaultFactories.Where(x => RuleInspector.Inspect(x.SelectionRules, memberInformation) == MemberSelectionResult.IncludeMember) .ToList(); if (matchingFactories.Count == 1) { return(matchingFactories.Single()); } //Check if multiple factories have matched if (matchingFactories.Any()) { throw new CreateInstanceException( $"Found multiple matching factories for member (in global configuration). Type is '{memberInformation.MemberType}'. Please make sure only one factory matches the member.", null, DefaultFactories.StringJoin(Environment.NewLine), null, memberInformation); } // No factory found return(null); }
public static T CreateInstance <T>([NotNull] this ICreateInstanceOptionsComplete <T> options) where T : class { options.ThrowIfNull(nameof(options)); //Create instance var rootMemberInformation = new MemberInformation { MemberType = typeof(T), MemberPath = String.Empty, MemberName = String.Empty }; var instance = CreateRootMember(options, rootMemberInformation); rootMemberInformation.MemberObject = instance; //Set each member of the created instance. SetAllMembers(options, rootMemberInformation); return(instance); }
/// <summary> /// Gets the name for anonymous items. /// </summary> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <returns>Returns the name to use.</returns> private static String GetAnonymousItemName <T>(ICreateInstanceOptionsComplete <T> options) where T : class => options.AnonymousItemName ?? AnonymousItemName;
/// <summary> /// Gets a value determining whether collections should get populated or not. /// </summary> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <returns>Returns a value of true if collections should get populated or not.</returns> private static Boolean PopulateCollection <T>(ICreateInstanceOptionsComplete <T> options) where T : class => options.PopulateCollections ?? PopulateCollections;
/// <summary> /// Gets a value determining whether the children should be included or not. /// </summary> /// <exception cref="CreateInstanceException">No matching rule was found.</exception> /// <typeparam name="T">The type of the instance to create.</typeparam> /// <param name="options">Some create instance options.</param> /// <param name="memberInformation">The member to check.</param> /// <returns>Returns a value of true if the children should be included; otherwise, false.</returns> private static Boolean IncludeChildMembers <T>(ICreateInstanceOptionsComplete <T> options, IMemberInformation memberInformation) => ShouldMemberBeIncluded(memberInformation, options.MemberChildrenSelectionRules, DefaultMemberChildreSelectionRules);