GraphUtils.ProduceCollectionsPerTypeFromGraph

Posts   
 
    
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 15-Aug-2007 13:33:59   

If you just want a set of entities per type, please use: GraphUtils.ProduceCollectionsPerTypeFromGraph(collection)

Quote copied from another message. This is a very handy helper! Particularily if you could provide an overload like:


public Dictionary<Type, IEntityCollection2> ProduceCollectionsPerTypeFromGraph(IEntityCollection2[] collectionList)
        {
            Dictionary<Type, IEntityCollection2> toReturn = new Dictionary<Type, IEntityCollection2>();

            Dictionary<Guid, Dictionary<Guid, IEntity2>> adjacencyLists = new Dictionary<Guid, Dictionary<Guid, IEntity2>>();
            Dictionary<Guid, IEntity2> recursed = new Dictionary<Guid, IEntity2>();

            foreach( IEntityCollection2 collection in collectionList )
            {
                
            
            foreach (IEntity2 entity in collection)
            {
                if (!recursed.ContainsKey(entity.ObjectID))
                {
                    ProduceAdjacencyLists(entity, adjacencyLists, recursed);
                }
            }
        }
            // recursed contains all entities in the graph. Walk it and per type, create a new entity collectionList, nongeneric. 
            foreach (KeyValuePair<Guid, IEntity2> pair in recursed)
            {
                IEntityCollection2 newCollection = null;
                if (!toReturn.TryGetValue(pair.Value.GetType(), out newCollection))
                {
                    newCollection = new EntityCollectionNonGeneric(pair.Value.GetEntityFactory());
                    toReturn.Add(pair.Value.GetType(), newCollection);
                }
                newCollection.Add(pair.Value);
            }

            return toReturn;
        }

The reason this overload would be good is that it allows merging from multiple collections.

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 15-Aug-2007 14:32:48   

If I understand your needs, then for v2.5, there is another option. The code below (not fully tested though) inherits from ReferencedEntityMap, which is used for fast serialization, lets it do the finding of all the entities in a graph (plus won't create ObjectIDs which aren't already there) and then analyses the Types and Counts of all found entities. You can then get them by type.

I was just using this in some unit tests to check that different queries were bringing back the same type and number of entities.

You could add a ctor to allow adding any number of collections/entities etc. before analyze() is called.

    public class ReferencedEntityMapAce: ReferencedEntityMap
    {
        List<Type> entityTypes;
        Dictionary<Type, int> instanceCount;
        EntityCollectionNonGeneric allEntities;

        public ReferencedEntityMapAce(object root): base(root)
        {
            analyze();
        }

        public List<Type> EntityTypes
        {
            get { return entityTypes; }
        }

        public int GetCount(Type entityType)
        {
            int result = 0;
            instanceCount.TryGetValue(entityType, out result);
            return result;
        }

        public int GetCount<T>() where T: EntityBase2
        {
            return GetCount(typeof(T));
        }

        public EntityCollectionNonGeneric GetCollection(Type entityType)
        {
            EntityCollectionNonGeneric result = new EntityCollectionNonGeneric();
            
            foreach(EntityBase2 entity in allEntities)
            {
                if (entity.GetType() == entityType) {
                    result.Add(entity);
                }
            }
            return result;
        }

        public EntityCollection<T> GetCollection<T>() where T: EntityBase2
        {
            EntityCollection<T> result = new EntityCollection<T>();
            
            foreach(EntityBase2 entity in allEntities)
            {
                T matchingEntity = entity as T;
                if (matchingEntity != null) {
                    result.Add(matchingEntity);
                }
            }
            return result;
        }

        void analyze()
        {
            entityTypes = new List<Type>();
            instanceCount = new Dictionary<Type, int>();
            allEntities = new EntityCollectionNonGeneric();
            allEntities.AddRange(GetSeenEntities());
            foreach(EntityBase2 entity in allEntities)
            {
                Type entityType = entity.GetType();
                int existingCount;
                if (instanceCount.TryGetValue(entityType, out existingCount))
                {
                    instanceCount[entityType] = existingCount + 1;
                }
                else
                {
                    entityTypes.Add(entityType);
                    instanceCount[entityType] = 1;
                }
            }
        }
    }

arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 04-Sep-2007 14:32:58   

Bump. Would you consider adding this change in v2.6?

This is a very handy helper! Particularily if you could provide an overload like: Code:

public Dictionary<Type, IEntityCollection2> ProduceCollectionsPerTypeFromGraph(IEntityCollection2[] collectionList) { Dictionary<Type, IEntityCollection2> toReturn = new Dictionary<Type, IEntityCollection2>();

        Dictionary<Guid, Dictionary<Guid, IEntity2>> adjacencyLists = new Dictionary<Guid, Dictionary<Guid, IEntity2>>();
        Dictionary<Guid, IEntity2> recursed = new Dictionary<Guid, IEntity2>();

        foreach( IEntityCollection2 collection in collectionList )
        {


        foreach (IEntity2 entity in collection)
        {
            if (!recursed.ContainsKey(entity.ObjectID))
            {
                ProduceAdjacencyLists(entity, adjacencyLists, recursed);
            }
        }
    }
        // recursed contains all entities in the graph. Walk it and per type, create a new entity collectionList, nongeneric.
        foreach (KeyValuePair<Guid, IEntity2> pair in recursed)
        {
            IEntityCollection2 newCollection = null;
            if (!toReturn.TryGetValue(pair.Value.GetType(), out newCollection))
            {
                newCollection = new EntityCollectionNonGeneric(pair.Value.GetEntityFactory());
                toReturn.Add(pair.Value.GetType(), newCollection);
            }
            newCollection.Add(pair.Value);
        }

        return toReturn;
    }

The reason this overload would be good is that it allows merging from multiple collections.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 04-Sep-2007 16:09:15   

Will do.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 12-Apr-2008 15:01:14   

Added to v2.6

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 12-Apr-2008 20:07:45   

Thanks