2

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);
}
George Duckett
  • 31,770
  • 9
  • 95
  • 162
  • And the actual problems you are facing? – Ondrej Tucny Dec 16 '11 at 11:40
  • If the object pool contains a list of BaseClass, how do i find my DerivedClass instance that i want? Iterating the list will be too slow. – George Duckett Dec 16 '11 at 11:43
  • Why slow? What number of instances are you thinking of? The answer to your question heavily depends on the inner workings of `EntityTemplate` and `MagicComponentPool`. You didn't descibe how you recognized individual components. By type? By some kind of ID? – Ondrej Tucny Dec 16 '11 at 12:08
  • Sorry, i might not have explained myself well. `EntityTemplate` is simply an object with a string property, and a list of `BaseComponent`. `MagicComponentPool` is what i want to create. If i give the `MagicComponentPool` an instance of a child of `BaseComponent` i'd like to get back another instance of the same type, that i can happily use (without effecting the one i passed in). The pool could have hundreds of instances of different child classes in it, as many could be in use, then all expire at the same time. – George Duckett Dec 16 '11 at 12:12

1 Answers1

1

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);
            }
        }
Bartosz Wójtowicz
  • 1,321
  • 10
  • 18