使 JSON 反序列化器区分 class 和 class 的子 class

Make JSON deserialiser distinguish between a class and a subclass of that class

在我正在处理的 asp.net 核心 mvc 应用程序中,我使用会话来跟踪我创建的名为 "Rule".

的模型的实例列表

现在,你不能在会话中保存字符串和整数以外的对象,我很确定,所以我写了一个会话扩展来序列化和反序列化对象,这样我就可以将它们保存在会话中。

我 运行 遇到的主要问题是规则可以包含仅具有牌面的 "Card" 或 "SuitedCard",它继承了 Card 并具有牌套。

因此,当我序列化然后反序列化列表时,所有 SuitedCards 变成卡片(导致卡片套装消失),我假设因为这是模型的默认值。

我该如何解决这个问题?我可以在会话扩展中添加一些有助于区分的东西,还是这是一个失败的原因?

在用子类尝试这个之前,我尝试使用接口做同样的事情,但问题是会话扩展试图实例化接口,这会导致错误。

SessionExtention

    public static class SessionExtentions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);

            return value== null ? default(T):
                JsonConvert.DeserializeObject<T>(value);
        }
    }

控制器中的规则列表

        private List<Rule> _ruleList;
        private List<Rule> RuleList
        {
            get
            {
                if (_ruleList == null)
                    _ruleList = HttpContext.Session.Get<List<Rule>>("RuleList");
                return _ruleList;
            }
            set
            {
                _ruleList = value;
                HttpContext.Session.Set("RuleList", _ruleList);
            }
        }

我将项目添加到列表的操作

        [HttpPost()]
        public IActionResult CreateRuleSet (CreateRuleSetViewModel model)
        {
            if (RuleList == null)
            {
                RuleList = MockDb;
            }
            List<Rule> rules = new List<Rule>();
            rules.AddRange(RuleList);
                Card card = new Card();
                if (model.CheckBox)
                {
                    card = new SuitedCard(model.Face, model.Suit);
                }
                else
                {
                    card.Face = model.Face;
                }
                rules.Add((new Rule(card, model.Type, 0)));
            RuleList = rules;
            model.Rules = rules;
            return View(model);
        }

当我向列表添加新规则并且页面刷新时,所有用于包含 SuitedCards 的规则现在都包含常规卡片。他们应该保持 SuitedCards。

你试过了吗

public static void Set<T>(this ISession session, string key, T value)
{
    session.SetString(key, JsonConvert.SerializeObject(value, new 
    JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }));
}

这将在 Json 中包含 class 名称,因此有助于在反序列化过程中更好地识别类型。