public bool Check(IRelevantObject relevantObject, RelevantObjectsGenerator generator)
 {
     return(Predicates.Count == 0 || Predicates.Any(o => o.Check(relevantObject, generator)));
 }
        public RelevantObjectCollection GetSubset(SelectionPredicateCollection predicate, RelevantObjectsGenerator generator)
        {
            var result = new RelevantObjectCollection();

            if (predicate == null)
            {
                foreach (var kvp in this)
                {
                    result.Add(kvp.Key, kvp.Value);
                }

                return(result);
            }

            foreach (var kvp in this)
            {
                result.Add(kvp.Key, kvp.Value.Where(o => predicate.Check(o, generator)).ToList());
            }

            return(result);
        }
Example #3
0
        /// <summary>
        /// Regenerates the relevant objects of this layer using the active generators. Any relevant objects that already exist do not get replaced and any relevant objects that should not exist get removed.
        /// </summary>
        public void GenerateNewObjects(bool forcePropagate = false)
        {
            if (GeneratorCollection == null)
            {
                return;
            }

            // Get all active generators for this layer
            var activeGenerators = GeneratorCollection.GetActiveGenerators().ToArray();

            // Get the previous layers objects if any generators are deep
            var deepObjects = activeGenerators.Any(o => o.Settings.IsDeep) ? GetAllPreviousLayersCollection() : null;

            // Initialize list for objects to add later
            var objectsToAdd = new List <IRelevantObject>();

            // Loop through all active generators
            foreach (var generator in activeGenerators)
            {
                // Get the generator methods
                var methods = generator.GetGeneratorMethods();

                // Get the required relevant object collection for this generator
                var objects = generator.Settings.IsDeep ?
                              deepObjects.GetSubset(generator.Settings.InputPredicate, generator) :
                              PreviousLayer?.Objects?.GetSubset(generator.Settings.InputPredicate, generator);

                // Loop through all generator methods in this generator
                foreach (var method in methods)
                {
                    // Get the dependencies for this generator method
                    var dependencies = RelevantObjectsGenerator.GetDependencies(method);

                    // Continue if there are dependencies but nothing to get the values from
                    if (dependencies.Length > 0 && PreviousLayer == null)
                    {
                        continue;
                    }

                    // Get all the combinations of relevant objects to use this generator method on
                    var parametersList =
                        RelevantObjectPairGenerator.GetParametersList(dependencies, objects,
                                                                      generator.Settings.IsSequential);

                    // Generate all the new relevant objects
                    foreach (var parameters in parametersList)
                    {
                        // Generate the new relevant object(s)
                        var result = method.Invoke(generator, parameters);

                        // Cast parameters to relevant objects
                        var relevantParents = new HashSet <IRelevantObject>(parameters.Cast <IRelevantObject>());

                        // Handle different return types
                        switch (result)
                        {
                        case IEnumerable <IRelevantObject> newRelevantObjectsEnumerable: {
                            // Enumerate to array
                            var newRelevantObjectsArray =
                                newRelevantObjectsEnumerable as IRelevantObject[] ??
                                newRelevantObjectsEnumerable.ToArray();

                            // Add the new relevant objects to the children of the parents
                            foreach (var relevantParent in relevantParents)
                            {
                                relevantParent.ChildObjects.UnionWith(newRelevantObjectsArray);
                            }

                            // Add parents and generator to the new relevant objects
                            foreach (var relevantObject in newRelevantObjectsArray)
                            {
                                relevantObject.Generator     = generator;  // Generator has to be set before parents, otherwise temporal position will go wrong
                                relevantObject.ParentObjects = relevantParents;

                                // Set the IsInheritable setting according to the generator settings
                                relevantObject.IsInheritable = generator.Settings.GeneratesInheritable;
                            }

                            // Add the new relevant objects to this layer
                            objectsToAdd.AddRange(newRelevantObjectsArray);
                            break;
                        }

                        case IRelevantObject newRelevantObject:
                            // Add the new relevant object to the children of the parents
                            foreach (var relevantParent in relevantParents)
                            {
                                relevantParent.ChildObjects.Add(newRelevantObject);
                            }

                            // Add parents and generator to the new relevant object
                            newRelevantObject.Generator     = generator;  // Generator has to be set before parents, otherwise temporal position will go wrong
                            newRelevantObject.ParentObjects = relevantParents;

                            // Set the IsInheritable setting according to the generator settings
                            newRelevantObject.IsInheritable = generator.Settings.GeneratesInheritable;

                            // Add the new relevant objects to this layer
                            objectsToAdd.Add(newRelevantObject);
                            break;
                        }
                    }
                }
            }

            // Avoid adding too many objects
            var newCount = objectsToAdd.Count + Objects.GetCount();
            var overshot = newCount - ParentCollection.MaxObjects;

            if (overshot > 0)
            {
                return;
                //objectsToAdd.RemoveRange(objectsToAdd.Count - overshot, overshot);
            }

            // Set all DoNotDispose to false
            foreach (var relevantObject in Objects.Values.SelectMany(list => list))
            {
                relevantObject.DoNotDispose = false;
            }

            // Add objects to this layer
            // This sets DoNotDispose for all the relevant objects that already exist in this layer and are consuming the objects to add.
            Add(objectsToAdd, false);

            // Dispose all relevant objects in this layer that were generated from a generator, but not generated now.
            foreach (var objectLayerObject in Objects.Values)
            {
                for (var i = 0; i < objectLayerObject.Count; i++)
                {
                    var obj = objectLayerObject[i];
                    // Continue for relevant objects with no generator or DoNotDispose
                    if (!obj.DefinitelyDispose && (obj.Generator == null || obj.DoNotDispose))
                    {
                        continue;
                    }
                    obj.Dispose();
                    i--;
                }
            }

            // Don't propagate if this layer has more than the max number of relevant objects
            if (Objects.GetCount() > ParentCollection.MaxObjects)
            {
                return;
            }

            // Propagate if anything was added to this layer
            if (objectsToAdd.Count > 0 || forcePropagate)
            {
                NextLayer?.GenerateNewObjects(forcePropagate);
            }
        }