自动化游戏的对象存储库

时间:2014-01-08 16:17:19

标签: c#

大家好,我在设计游戏的对象存储库时遇到问题:

class ObjectRepository
{

private readonly LevelType _levelType;

private readonly BaseObject[] _darkForestObjects = new BaseObject[] 
                { new DarkForestTreeA(), new DarkForestTreeB(), new DarkForestTreeC() };

private readonly BaseObject[] _lightForestObjects = new BaseObject[] 
                { new LightForestTreeA(), new LightForestTreeB(), new LightForestTreeC() };

public ObjectRepository(LevelType lt)
{
    _levelType = lt;
}

public BaseObject GetObject(int obj)
{
    if (obj < 0 || obj > _darkForestObjects.Length)
    {
        Debug.LogError("Object does not exist.");
        return null;
    }

    switch (_levelType)
    {
        case LevelType.DarkForest:
           return _darkForestObjects[obj];
        case LevelType.LightForest:
           return _lightForestObjects[obj];
    }

    return null;
}
}

public enum LevelType
{
    DarkForest = 0,
    LightForest = 1,
}

我正在寻找一种自动化这个类的方法。通过自动化它我的意思是我不希望每次我创建一个从BaseObject派生的新对象进入Repository类并修改数组。它只是没有看起来很自然。有人能指出我对自动化的建议吗?

2 个答案:

答案 0 :(得分:1)

我会对此感到愤怒,所以如果我做错了,请告诉我。

你需要:

  • 将保存您的BaseObject派生实例的存储库;
  • BaseObject类必须可以访问所述存储库;
  • 每当创建一个BaseObject时,它就会将自己添加到存储库中。

现在,我注意到您保存了对象的 dark light 版本的实例。所以我还建议给出一个给定“对象”的明暗版本的持有者类。像这样:

class CompoundObject
{
    public BaseObject LightVersion;
    public BaseObject DarkVersion;
}

然后您的存储库保留CompoundObject - 派生对象,而不是在创建时添加自己的BaseObject个对象,CompoundObject对象就可以执行此操作。

现在关于数组操作,你可能是对的;它有点笨重。我建议采用List<CompoundObject>代替CompoundObject[]。通用List提供非常方便的方法,如添加和删除,可以简化您的集合操作。

答案 1 :(得分:1)

如果我是你,我会选择使用接口的更通用的解决方案。 考虑到您的示例,我假设您有多个级别类型,它们具有自己特定的TreeA,TreeB和TreeC实现。 如果我理解正确,我宁愿为每种树类型使用接口。 TreeA的示例:

public interface ITreeA
{
  // any common public members here
}

public class DarkForestTreeA : ITreeA, BaseObject
{
    ...
}

public class LightForestTreeA : ITreeA, BaseObject
{
    ...
}

这样,您可以要求您的存储库提供特定于级别类型的ITreeA实现。类似的东西:

public T GetObject<T>() // where T could be ITreeA, ITreeB...
{
    ...
}

因此,如果级别类型为DarkForest,则可以调用myRepo.GetObject()并获取DarkForestTreeA对象。

要实现此行为&#34;自动化&#34;,您可以在唯一的命名空间中声明DarkForest的所有特定实现,然后使用反射来查找实现ITreeA的命名空间的类。这在性能方面可能效率不高,但它为您提供了极大的灵活性,因为您只需在命名空间中添加新类即可从存储库中获取它们。但是,它也可能带来其他问题(例如,如果在同一名称空间中有两个实现ITreeA的类会发生什么?)。 有关实施详情,请参阅Getting all types in a namespace via reflectionGetting all types that implement an interface with C# 3.0

我必须承认这不是最简单的解决方案。

您可以考虑更简单的事情,例如为对象类型定义字典(treeA,treeB),然后为每种级别类型定义字典,将对象类型映射到其具体实现。 例如:

public enum ObjectType
{
    TreeA,
    TreeB,
    TreeC,
}

Dictionary<ObjectType, Type> DarkForestObjectTypes = new Dictionary<ObjectType, Type>()
{
    { ObjectType.TreeA, typeof(DarkForestTreeA) },
    { ObjectType.TreeB, typeof(DarkForestTreeB) }
    ...
}

由于这个答案看起来有些混乱,我不会详细了解更多细节,但希望它会给你提供继续的想法。