c# - 类设计 - 几种可能类型的属性

标签 c# json

取一个 Player 类,它(当前)有一个 Role 类型的属性:

public class Player
{
    public string Name { get; set; }
    public int Health { get; protected set; }
    public Role Role { get; set; }
}

Role 包含几个不同的值:

public class Role
{
    public double DamageModifier { get { return _damageModifier; } }
    public double DefenseModifier { get { return _defenseModifier; } }
    public double HealthModifier { get { return _healthModifier; } }

    private double _damageModifier;
    private double _defenseModifier;
    private double _healthModifier;

    public Role(double damageMod, double defenseMod, double healthMod)
    {
        _damageModifier = damageMod;
        _defenseModifier = defenseMod;
        _healthModifier = healthMod;
    }
}

还有一些从 Role 派生的“类”:

public class Archer : Role
{
    private const double _damageModifier = 1.2;
    private const double _defenseModifier = 0.9;
    private const double _healthModifier = 0.8;

    public Archer() : base(_damageModifier, _defenseModifier, _healthModifier) { }
}

public class Mage : Role
{
    private const double _damageModifier = 1.4;
    private const double _defenseModifier = 0.7;
    private const double _healthModifier = 0.9;

    public Mage() : base(_damageModifier, _defenseModifier, _healthModifier) { }
}

public class Warrior : Role
{
    private const double _damageModifier = 1.0;
    private const double _defenseModifier = 1.2;
    private const double _healthModifier = 1.0;

    public Warrior() : base(_damageModifier, _defenseModifier, _healthModifier) { }
}

所有这一切的最终结果实际上只是 Player.Role 属性是将成为 ArcherMage 的占位符, 或 Warrior。然而,这个特定的子类型是在运行时决定的(或者更具体地说,是在角色创建时)。

我遇到的问题是尝试将播放器对象序列化JSON 数据。当 JSON 序列化 Role 属性时,它知道它是一个 Role 对象,并且能够得到相应的 xxModifier来自实例的值,但我忘记了 Role 属性是从 Role 派生的类这一事实。

我显然还在学习,但这类问题告诉我我在设计这个类时搞砸了,它需要修复。我可以重构构造函数,以便 Role 持有对子类的引用,但这似乎也是错误的。

编辑 根据评论: 我对 Archer/Mage/Warrior 类的意图是,除了当前存在的 xxModifier 属性之外,每个类都将具有某些可用的方法(能力),例如Warrior 会造成(相对)更少的伤害,但具有更高的防御和生命值,而 Role 类目前用作给 Player 对象一个地方来担任他的角色(RPG 类)。这个具体的实现是我的目标,这里列出的是我到目前为止的想法。

  • 在这种情况下是否需要 Role 类?
  • 假设重新设计这些类是必要的,我怎样才能最好地编写它,以便 Player 对象 Archer/法师/战士?

最佳答案

对于如何在保留类型的同时序列化和反序列化为 JSON 的直接问题,使用像 JSON.Net 这样的东西,这是非常简单的:

var p = new Player() { Role = new Mage() };
var json = JsonConvert.SerializeObject(p, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Objects });

现在你的 JSON 看起来像这样:

{
    "$type": "MyApp.Program+Player, MyApp",
    "Name": null,
    "
Health": 0,
    "Role": {
        "$type": "MyApp.Program+Mage, MyApp",
        "DamageModifier": 1.4,
        "DefenseModifier": 0.7,
        "HealthModifier": 0.9
    }
}

添加了额外的 $type 属性,因此当您反序列化时:

var d = (Player)JsonConvert.DeserializeObject(json, typeof(Player), new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Objects });
var isMage = d.Role.GetType() == typeof(Mage);  // true

关于您的设计是否是个好主意(如评论中所讨论)的问题范围更广。

关于c# - 类设计 - 几种可能类型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34642568/

相关文章:

c# - 如何检索 longblob 列的二进制内容并另存为文件?

c# - 如何将嵌套的 json 配置绑定(bind)到 .net core 中的选项

c# - 使用 Azure、Https 和远程 HTTP 调用组合删除 session

javascript - 根据键值选择根节点

java - 转换 JSON 结构

c# - 如何过滤JArray?

C# 将枚举转换为字符

c# - 搜索用户并按 Redis 中最多的共同 friend 数量排序?

javascript - 如何访问 JSON 对象属性

c# - 无法隐式转换类型 'System.Collections.Generic.List