Search code examples
c#genericsinheritancegeneric-collectionsobject-pooling

One object pool to contain different derived classes


Short version:

How would i go about creating an object pool that can store classes of different types all derived from the same base class?
See below for an example of expected usage.


Long version:

I have a class BaseComponent, with many derived classes e.g. Child1Component, Child2Component.

I also have another object that represents a collection of these components, with their properties set to specific values. I call this an EntityTemplate, since an entity is defined by the set of components and their values.

I want to create entities based on entity components. To do this currently i get the appropriate EntityTemplate, loop through it's different components and call a Clone method I've defined on each child class. I also have a Copy method defined there too, which might be useful.

When an entity expires i'd like to add its components to an object pool, then when i next need to create an entity i'd get the entity template and for each component i'd get one of the same type out of the pool and set it's properties equal to the one in the EntityTemplate, something like below:

// What i want to do
var entityTemplate = GetTemplate("UniqueString");
var MyActualEntity = new Entity();

foreach(var componentTemplate in entityTemplate)
{
    var actualComponent = MagicComponentPool
                              .GetComponentSameTypeAsParam(componentTemplate);
    actualComponent.CopyFrom(componentTemplate);

    MyActualEntity.Components.Add(actualComponent);
}

Solution

  • I would use a dictionary.

    Dictionary<Type, BaseComponent> dictionary = new Dictionary<Type, BaseComponent>();
    

    put the original components in like this:

    dictionary.Add(component.GetType(), component);
    

    and retrieve them by type.

    BaseComponent component = dictionary[componentTemplate.GetType()];
    

    Complexity of retrieving objects from dictionaries is constant no matter how many objects there’s in the dictionary and is equal to the cost of calculating the hash of the key.

    However, I’m not sure if that is applicable for your purpose, but as you are copying the objects anyway, why not just clone the components from the template or even clone the whole template.

    Here’s a generic Clone method for you:

    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
            public static T Clone<T>(T o)
            {
                byte[] bytes = SerializeBinary(o);
                return DeserializeBinary<T>(bytes);
            }
    
            public static byte[] SerializeBinary(object o)
            {
                if (o == null) return null;
                BinaryFormatter bf = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    bf.Serialize(ms, o);
                    return ms.GetBuffer();
                }
            }
    
            public static T DeserializeBinary<T>(byte[] bytes)
            {
                if (bytes == null) return default(T);
                BinaryFormatter bf = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    return (T) bf.Deserialize(ms);
                }
            }