一个对象池包含不同的派生类

时间:2011-12-16 11:30:18

标签: c# generics inheritance generic-collections object-pooling

简短版:

我如何创建一个可以存储所有派生自同一基类的类的对象池?
请参阅下面的预期用法示例。


长版:

我有一个班级BaseComponent,有许多派生类,例如Child1ComponentChild2Component

我还有另一个对象,它表示这些组件的集合,其属性设置为特定值。我称之为EntityTemplate,因为实体是由组件集及其值定义的。

我想基于实体组件创建实体。为了做到这一点,我现在得到了相应的EntityTemplate,遍历它的不同组件并调用我在每个子类上定义的Clone方法。我也在那里定义了Copy方法,这可能很有用。

当一个实体到期时我想将它的组件添加到一个对象池中,那么当我接下来需要创建一个实体时,我会获得实体模板,而对于每个组件,我会得到一个相同的类型对于池并设置它的属性等于EntityTemplate中的属性,如下所示:

// 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);
}

1 个答案:

答案 0 :(得分:1)

我会用字典。

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

将原始组件放入:

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

并按类型检索它们。

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

从字典中检索对象的复杂性是不变的,无论字典中有多少个对象,并且等于计算密钥散列的成本。

但是,我不确定这是否适用于您的目的,但是当您正在复制对象时,为什么不从模板中克隆组件甚至克隆整个模板。

以下是适用于您的通用克隆方法:

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);
            }
        }