【问题标题】:Nested string to class deserialization using YamlDotNet使用 YamlDotNet 将字符串嵌套到类反序列化
【发布时间】:2021-09-24 12:08:54
【问题描述】:

我需要能够在运行时将字符串(作为属性)动态反序列化为类。我还需要能够以支持嵌套的方式执行此操作。

示例 - 发射爆炸子弹的炮塔

Turret.yaml

Type: Turret
Name: MiniTurret
DisplayName: Mini Turret
MaxHP: 100
Damage: 50
TurretTurnSpeed: 20
Sprite: turret_1
ProjectileName: ExplosiveBullet

ExplosiveBullet.yaml

Type: Bullet
Name: ExplosiveBullet
DisplayName: Explosive Bullet
Damage: 50
TurretTurnSpeed: 20
Sprite: explosivebullet1
Components:
   - ExplosionComp:
      - ExplosionType: Incendiary
      - Damage: 10
      - Radius: 5

我们正在尝试创建一个炮塔(使用 Turret.cs 类,如“类型”字段中所述),它可以发射 Def 名称为“ExplosiveBullet”的射弹。在运行时,我们将字符串“ExplosiveBullet”反序列化为适当的类。项目符号现在对组件列表执行相同的操作 - 它需要将字符串“ExplosionComp”反序列化为 ExplosionComp.cs,并传入 Damage 和 Radius 值。

这样,我正在尝试创建一个嵌套组件系统,该系统可以引用其他组件(例如炮塔引用子弹,子弹引用它被摧毁时产生的爆炸效果)。

是否必须使用反射来解决这个问题? YamlDotNet 中是否有专门用于处理此问题的内容?

我见过过时或复杂的解决方案; YamlDotNet 有没有很好的方法来处理这个问题?

【问题讨论】:

  • 与 Unity 已经提供的组件系统有何不同?就像您要解决的确切目标是什么?为什么不简单地拥有 GameObject 预制件或 ScriptableObjects?为什么 YAML(一般不反对 YAML 但是)为什么不呢?内置支持且传播范围非常广泛的 JSON -> 在线存在大量材料
  • 在我的游戏中,我使用 tilemaps 并且会尽量保持 GameObject 预制件最少。可编写脚本的对象可以解决问题,但使用 YAML,我可以更改 .yaml 中的某些内容、保存它、在运行时在游戏中重新加载它,并且无需重新启动即可立即看到更改。 YAML 也对模组更友好。我没有反对 JSON,我只是认为 YAML 总体上看起来更好,并且应该以相同的方式工作。不管是 YAML 还是 JSON,这仍然是一个有效的问题,而《RimWorld》游戏正是采用了这种方法。
  • 那么也许我不太明白你的问题到底是什么......你在使用YamlDotNet 时有什么问题吗?还是您对所需的数据结构有疑问?
  • 问题是使用 YamlDotNet,或者一般来说是基于文本的序列化格式,在单个文件中反序列化多个类的多个对象

标签: c# reflection yaml deserialization yamldotnet


【解决方案1】:

YAML 1.2 规范包括 anchors,它允许您在一个地方创建对对象的引用并在另一个地方使用它们。

但是,该规范 also makes it clear 预计 YAML 文件将完全相互独立。没有标准方法可以从另一个文件中引用一个文件的内容。

我建议将您的 YAML 文件读入数据传输对象层,您可以在其中允许简单的字符串属性仅通过其唯一 ID 包含对其他对象的引用。然后通过将对象引用连接到从具有引用 ID 的 DTO 创建的对象,将这些 DTO 转换为您的对象模型层。这有点像手动映射过程,但它提供了良好的关注点分离。

【讨论】:

  • 我从未听说过锚点或 DTO,因此我什至不知道这种模式是什么样的,也不知道如何开始实施它。您能否使用完整的初学者的代码更新您的答案,或者向我指出一些有关如何执行此操作的资源?另外,这是唯一的解决方案吗?我们不能在运行时使用反射来构建类吗?
  • 我真的没有时间详细说明。 DTO 只是一个 C# 类,其属性直接反映 YAML 的结构,因此您可以轻松地直接反序列化为强类型 C# 对象。还有很多其他可能的解决方案:您可以反序列化为字典并编写更多手动代码以将其映射到您的模型中;您可以编写自定义反序列化代码(例如 IYamlTypeConverter)来使 ProjectileName 和 ExplosionType 等某些属性导致其他 YAML 文件被打开和反序列化。天空才是极限。
  • "我们不能在运行时使用反射来构建类吗?"这就是反序列化的作用。
猜你喜欢
  • 1970-01-01
  • 2018-03-02
  • 2016-01-05
  • 1970-01-01
  • 2023-04-01
  • 2020-06-09
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多