Esempio n. 1
0
        /// <summary>
        /// Traverse the result object graph, flattening into a single list. Note that this
        /// flattening must maintain relative ordering for the top level elements, since the client might
        /// have passed an order expression.
        /// </summary>
        /// <typeparam name="TEntity">The root entity Type of the query.</typeparam>
        /// <param name="list">The list of entities to add to the results.</param>
        /// <param name="rootResults">The root entities. The value can be <value>null</value> if the list of root results is already known.</param>
        /// <param name="includedResults">The included entities.</param>
        /// <param name="visited">Map used for the lifetime of the flattening to ensure that each entity
        /// is added to the results only once.</param>
        /// <param name="domainServiceDescription">description for the DomainService.</param>
        private static void FlattenGraph <TEntity>(IEnumerable list, List <TEntity> rootResults, List <object> includedResults, HashSet <object> visited, DomainServiceDescription domainServiceDescription)
        {
            if (list == null)
            {
                return;
            }

            // Queue used for breadth-first scan
            Queue <IEnumerable> resultsQueue = new Queue <IEnumerable>();

            resultsQueue.Enqueue(list);

            IList result = rootResults;

            while (resultsQueue.Count > 0)
            {
                foreach (object entity in resultsQueue.Dequeue())
                {
                    if (!visited.Add(entity))
                    {
                        continue;
                    }

                    // If we already know the root results, then we don't need to copy them over to a new list.
                    if (result != null)
                    {
                        result.Add(entity);
                    }

                    // make sure to use the correct entity Type, taking inheritance into account
                    Type entityType = domainServiceDescription.GetSerializationType(entity.GetType());
                    PropertyDescriptorCollection properties = MetaType.GetMetaType(entityType).IncludedAssociations;
                    foreach (PropertyDescriptor pd in properties)
                    {
                        IEnumerable value = null;
                        if (typeof(IEnumerable).IsAssignableFrom(pd.PropertyType))
                        {
                            value = (IEnumerable)pd.GetValue(entity);
                        }
                        else
                        {
                            // singleton association
                            object singleton = pd.GetValue(entity);
                            if (singleton != null)
                            {
                                value = new object[] { singleton };
                            }
                        }

                        if (value != null)
                        {
                            resultsQueue.Enqueue(value);
                        }
                    }
                }

                // From now on, add everything to includedResults.
                result = includedResults;
            }
        }