【问题标题】:How do I reconstruct class name references independent of name changes?如何重建独立于名称更改的类名称引用?
【发布时间】:2017-06-20 23:41:16
【问题描述】:

这是一个普遍的问题,我相信它已经解决了。

我有几个类(实体系统的组件),我想在文件(字符串或标志)中保存对类的某种引用,作为保存/加载系统的一部分。但是我希望能够随着时间的推移在 C# 中更改类的名称,并让它在下次自动重建正确的数据,而无需手动迁移数据。

目前我认为有办法自动完成这一切,假设 C# 中所有引用的类不会立即更改。我可以进行字符串检查以消除可以解析的引用 - 然后显示一个 UI 弹出窗口来解决类似“哦,Renderable 类已更改,看起来模型的关卡数据都指向这个,是不是同一个班?”。我还可以使用反射查找函数名称来构建相关类的“元数据配置文件”(与其名称标签区分开来),因此数据问题与 GetType().GUID 或其他任何东西(初始化顺序?)无关。

如果我创建某种简单类型的数据库,那么标志值将在第一个会话中生成,然后在实际关卡文件中查找并为该特定关卡文件重新洗牌。但这是它变得复杂的地方,那就是不好或没有帮助。如果数据库文件丢失了,并且在加载关卡文件时有 200 多种类型需要解析。

也许有更简单的方法。但是就信息而言,只有 cpu 可以知道的实际类成员/字段,而没有明确指定和关注它。对于此类数据问题,没有任何方法可以引发错误,也没有验证检查。

我的一个想法是在定义类时使用互斥标签 - 强制它们使用模板参数 T 继承 IDummy,其中 T 来自进一步的虚拟接口标签列表,因此您可以选择类似于枚举条目的东西,然后将其添加到字典(类型为键)中以引发进一步的错误,以防止程序在类定义和类功能之间没有一致的映射(独立于其名称标签)时运行。然后,如果我想永久删除数据中的一个类——我只需将其“标签”列入黑名单。

我通过依赖 C# 反射/元数据的模板技巧来完成所有这些工作。有可能,我知道。

对于每个轻量级对象(实体),存储的只是一个 id 和一个标志值。

【问题讨论】:

  • 首先,这听起来可怕;为什么不直接序列化为 JSON?不包含类型信息
  • 保存数据总是意味着你有这个问题。这是关于旧信息未链接到新信息的问题。 JSON 会对做某事的特定方式产生同样的焦虑,而该特定方式在程序的下一次运行中不会继续(因为类名标签已更改,因此所有内容都由此派生)这是一个需要解决的合法问题(数据在会话和程序结构更改之间)。如果您需要区分正在处理的类/类型,您总是需要类型信息!嗯,我想我应该停止避免使用明确的标志/哈希。
  • 仅仅因为你可以这样做并不意味着你应该那样做。退后一步,想想你真正想要达到的目标。有没有更好的办法?有更合理的吗?您已经听说过的一些模式?您将在我怀疑需要的地方引入很多复杂性。

标签: c# database logic


【解决方案1】:

使用反射,您可以深入任何程序集并提取您想要的任何内容,这是提取类名的示例。

   var asm = Assembly.Load("Some.Assembly.Name");
    var nameSpace = "Some.Namespace.Name";

    var classes = asm.GetTypes().Where(p =>
         p.Namespace == nameSpace &&
         p.Name.Contains("ClassNameFilter") 
    ).ToList();

【讨论】:

  • 这是一个“会话之间的数据”问题,而不是“字符串化类”问题。当类名更改时,可以比较所有以前的类名 - 但我可能想轮换类名或将它们改回来 - 这会出现您在解决方案中没有考虑的循环引用问题。
【解决方案2】:

好吧,我现在要做的是一个“肮脏”的解决方案,但它是一丝不苟的人可以忍受的事情之一。

我只是添加一个独立于会话/标签的标识符。我打算使用一个看起来更干净的模板参数。但我只需要指定 1、2 或 3 等作为我想要区分的类的某种编译时 id(这些是索引查找要实际使用的位标志值)

所以在类的第一行,我现在为类型 id 放置了一个静态 int。它还有很多内容(模板基类、单例、初始化顺序黑客),但至少现在它很简洁。唯一的事情是我必须为每个班级指定一个数字。 (程序绝对必须知道独立于类名)。

元数据的想法是一个糟糕的想法,因为如果我想克隆一个类/组件,就没有办法正确区分它(也许除了类型名称之外)。所以也许它可以工作。

我不想涉及“数据库”(文本文件映射会这样做 - 它会从编译器的命名顺序中转义初始化顺序),这可能是避免它的好主意,仅适用于那些极端情况(一个包含 1000 个游戏对象的数据库,我想突然更改所有的类名)

这只是固有的信息不足问题。几乎唯一的解决方案是明确它是哪个类(在所有其他上下文之外)并为重复的类型 id 抛出错误。

但是,当有关数据的某些事情发生变化时,我们并非无法推断出程序的行为。程序应该仍然有可能弄清楚什么是什么......除了,你有这样的情况,比如一个组件类与另一个组件类具有完全相同的字段和成员,因此除了类名之外它们都“看起来相同” ,在解决它是什么类时我们不能依赖它。 (在我的场景中,它可以随时更改)。

【讨论】:

  • 避免在会话/名称之间使用一致的类标识符 .. 是现代工业编程仍然没有解决的教条 OOP 问题。因此,从根本上讲,这是一个非常简单易懂的问题。在 C# 中,您不能简单地将具有值的类定义为模板参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-31
  • 1970-01-01
  • 2013-08-29
相关资源
最近更新 更多