【问题标题】:One object pool to contain different derived classes一个对象池包含不同的派生类
【发布时间】:2011-12-16 11:30:18
【问题描述】:

短版:

我将如何创建一个对象池来存储从同一个基类派生的不同类型的类?
请参阅下面的预期用法示例。


加长版:

我有一个类BaseComponent,有许多派生类,例如Child1Component, Child2Component.

我还有另一个对象表示这些组件的集合,它们的属性设置为特定值。我称之为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);
}

【问题讨论】:

  • 你面临的实际问题是什么?
  • 如果对象池包含 BaseClass 的列表,我如何找到我想要的 DerivedClass 实例?迭代列表会太慢。
  • 为什么慢?您考虑的实例数量是多少?您的问题的答案很大程度上取决于EntityTemplateMagicComponentPool 的内部运作。您没有描述如何识别单个组件。按类型?通过某种 ID?
  • 对不起,我可能没有很好地解释自己。 EntityTemplate 只是一个具有字符串属性的对象,以及 BaseComponent 的列表。 MagicComponentPool 是我想要创建的。如果我给MagicComponentPool 一个BaseComponent 的子实例,我想取回另一个相同类型的实例,我可以愉快地使用(不影响我传入的那个)。池中可能有数百个不同子类的实例,其中许多实例可能正在使用中,然后全部同时到期。

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


【解决方案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);
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    相关资源
    最近更新 更多