c# - 如何将 YAML 属性反序列化为具有传递参数的类?
问题描述
我正在尝试使用 YamlDotNet 实现在游戏“RimWorld”中使用 XML 实现的功能。
我知道如何反序列化基本信息,如下所示:instanceOfDeserializer.Deserialize<MyBaseClass>(someTextReaderInstance)
我正在尝试将派生类型列表反序列化为它们的基本类型列表。
目标是能够将字符串作为类名,并使用 YAML 中列出的参数对其进行实例化。以下是它在 XML 中的实现方式:
<ThingDef ParentName="ResourceBase">
<defName>Chemfuel</defName>
<label>chemfuel</label>
<description>A volatile liquid chemical. Used to fuel engines and rockets, or to transmute into propellant for projectiles, or as an incendiary weapon.</description>
<stackLimit>150</stackLimit>
<comps>
<li Class="CompProperties_Explosive">
<explosiveRadius>1.1</explosiveRadius>
<explosiveDamageType>Flame</explosiveDamageType>
<explosiveExpandPerStackcount>0.037</explosiveExpandPerStackcount>
<startWickOnDamageTaken>
<li>Flame</li>
</startWickOnDamageTaken>
<startWickHitPointsPercent>0.333</startWickHitPointsPercent>
<preExplosionSpawnThingDef>Filth_Fuel</preExplosionSpawnThingDef>
<preExplosionSpawnChance>1</preExplosionSpawnChance>
<wickTicks>70~150</wickTicks>
</li>
</comps>
</ThingDef>
该comps
列表是我想参考的外部类的列表。在这种情况下,我们想为 item 添加爆炸属性chemfuel
。似乎在 XML 中,开发人员使用Class="CompProperties_Explosive"
标签引用了想要的类。我需要在 YAML 文档中使用类似的功能。
以下是我在 YAML 文档中的设想:
Type: Item
Name: fuel_cansiter
DisplayName: Fuel Canister
Sprite: fuel_canister_1
MaxStackSize: 10
MaxHP: 15
Value: 30
Components:
- Explosive:
- Damage: 10
- Range: 25
- Burnable:
- FlameSize: 10
- HealthThreshold: 0.4
我想用和类作为组件来实例化这个FuelCanister
项目,但是通过 YAML 传递动态变量,例如损坏和范围。Explosive.cs
Burnable.cs
在这种情况下,派生类型是Explosive
and Burnable
,它们都应该能够反序列化为它们的基本类型,例如Component
。
最后,FuelCanister.cs
该类应该以一个Component
类型列表结束,从中派生 和Explosive
。Burnable
YamlDotNet 中是否有内置函数可以轻松执行此操作?
编辑:也许 XML 方式使用 XML 属性来提取类的名称,然后使用该名称,我们可以使用反射来实例化具有传递参数的类?有没有办法用 YAML 做到这一点?
解决方案
在 YAML 中,您通常使用tags指定类型。使用标签,您的 YAML 可能如下所示:
!Item
Name: fuel_cansiter
DisplayName: Fuel Canister
Sprite: fuel_canister_1
MaxStackSize: 10
MaxHP: 15
Value: 30
Components:
- !Explosive
Damage: 10
Range: 25
- !Burnable
FlameSize: 10
HealthThreshold: 0.4
在本文档中!Item
,!Explosive
和!Burnable
是标签。您可以定义它们映射到的类型。使用DeserializerBuilder
该类,您可以将标签与 .NET 类型相关联,如下所示:
var deserializer = new DeserializerBuilder()
.WithTagMapping("!Item", typeof(Item))
.WithTagMapping("!Explosive", typeof(Explosive))
.WithTagMapping("!Burnable", typeof(Burnable))
.Build();
这假设您有以下类:
class Item
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string Sprite { get; set; }
public int MaxStackSize { get; set; }
public int MaxHP { get; set; }
public int Value { get; set; }
public List<Component> Components { get; set; }
}
abstract class Component {}
class Explosive : Component
{
public int Damage { get; set; }
public int Range { get; set; }
}
class Burnable : Component
{
public int FlameSize { get; set; }
public double HealthThreshold { get; set; }
}
一旦你有了这个,你可以像这样反序列化:
var item = deserializer.Deserialize<object>(yaml);
在这种情况下,我使用object
了因为我假设您可能希望您的文档包含不同的对象类型。如果您事先知道该文档包含一个Item
,则可以删除该!Item
标签并使用它:
var item = deserializer.Deserialize<Item>(yaml);
推荐阅读
- android - CoordinatorLayout 中的渲染错误 - 我该如何解决?
- javascript - 如何使用javascript将csv更改为json数组
- css - css 属性问题“背景剪辑:文本;” 和 W3C 验证器
- jestjs - Jest-Puppeteer 测试随机失败而没有输出
- groovy - 如何在 Groovy 中使用 Dagger?
- javascript - 奇数值和 1 如何在 js 中给出“真”?
- python - 在python中将一些列转换为行,将一列的行转换为列
- python - 使用 AJAX、Python 和 CGI 上传文件
- google-bigquery - 从行中为每个成功条件返回多行
- uitableview - 没有 Xamarin.Forms 的 UITableView 标题背景颜色