internal static List <Type> GetFactoryInputTypes(List <Type> objectTypes) { List <Type> demandedTypes = new List <Type>(); foreach (Type t in objectTypes) { List <Type> dependencies = DiscoverableInputHelper.GetFactoryInputTypes(t); foreach (Type demandedType in dependencies) { if (!demandedTypes.Contains(demandedType)) { demandedTypes.Add(demandedType); } } } return(demandedTypes); }
/// <summary> /// Populates Input properties for a Factory or Action /// </summary> /// <param name="consumer">Object to be populated</param> /// <param name="random">Deterministic Random source</param> /// <param name="state">Supporting State Object</param> /// <param name="recursionLimit">Recursion depth - ie - how many parent invocations does the current code have?</param> /// <returns></returns> private static bool PopulateDiscoverableInputs(IDiscoverableObject consumer, DeterministicRandom random, ConvenienceStressState state, int recursionDepth) { List <PropertyDescriptor> inputProperties = DiscoverableInputHelper.GetInputProperties(consumer.GetType()); foreach (PropertyDescriptor property in inputProperties) { //Determine desired type Type consumedType = property.PropertyType; Object result = null; InputAttribute inputAttribute = (InputAttribute)property.Attributes[typeof(InputAttribute)]; if (inputAttribute == null) { inputAttribute = InputAttribute.CreateFromFactory; } switch (inputAttribute.ContentInputSource) { // case ContentInputSource.GetFromLogicalTree: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } //Get Property from window surface Area Trace.WriteLine("[DiscoverableActionSequencer] Getting a Logical Tree Item"); result = state.GetFromLogicalTree(consumedType, random); //For object from Logical tree, null means item not found, thus failed. if (result == null) { return(false); } break; case ContentInputSource.GetFromVisualTree: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } //Get Property from window surface Area Trace.WriteLine("[DiscoverableActionSequencer] Getting a Visual Tree item"); result = state.GetFromVisualTree(consumedType, random); //For object from Visual tree, null result means item not found, thus failed. if (result == null) { return(false); } break; case ContentInputSource.GetWindowListFromState: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } Trace.WriteLine("[DiscoverableActionSequencer] Getting WindowList property of state"); result = state.WindowList; break; //Populate data from Type.Property specific constraints system // case ContentInputSource.CreateFromConstraints: Trace.WriteLine("[DiscoverableActionSequencer] Getting a Constraint based item"); result = state.MakeFromConstraint(consumer.GetType(), property.Name, random); break; case ContentInputSource.GetFromObjectTree: Trace.WriteLine("[DiscoverableActionSequencer] Getting a object from Object tree."); result = state.GetFromObjectTree(consumedType, random); //For object from Object tree, null result means item not found, thus failed. if (result == null) { return(false); } break; //Default behavior is to produce content from factories default: if (recursionDepth < standardRecursionLimit || (recursionDepth < absoluteRecursionLimit && inputAttribute.IsEssentialContent)) { Trace.WriteLine("[DiscoverableActionSequencer] Producing factory content"); //Basic workflow for producing Factory content if (!consumedType.IsGenericType) { result = MakeItem(consumedType, state, random, recursionDepth + 1); } else { if (consumedType.GetGenericTypeDefinition() == typeof(List <>)) { result = MakeList(consumedType, state, random, recursionDepth + 1, inputAttribute.MinListSize, inputAttribute.MaxListSize); } else { throw new InvalidOperationException("We can't work with this type yet:. " + consumedType.GetGenericTypeDefinition()); } } } else if (recursionDepth >= absoluteRecursionLimit && inputAttribute.IsEssentialContent) { throw new InvalidOperationException("The stress test factory has reached the absolute recursion limit and is still demanding essential content. Is there a cyclic chain only involving factories requiring their inputs?"); } else //Factory Recursion depth exceeded. We are leaving non-essential property null { //No Operation } break; } //Set value to desired input property.SetValue(consumer, result); if (result != null) { Trace.WriteLine(String.Format("[DiscoverableActionSequencer] Provided a [{0}] of type {1} for {2}", result, result.GetType(), consumer)); } else { Trace.WriteLine(String.Format("[DiscoverableActionSequencer] Provided a null for {1}", result, consumer)); } } return(true); }