Сделайте, чтобы JSON deserialiser различал класс и подкласс этого класса - PullRequest
0 голосов
/ 27 мая 2019

В базовом mvc-приложении asp.net, над которым я работаю, я использую сеансы для отслеживания списка экземпляров модели, которую я создал под названием «Правило».

Теперь вы не можете сохранять объекты, отличные от строк и целых чисел в сеансах, я почти уверен, поэтому я написал расширение сеанса, которое сериализует и десериализует объекты, чтобы я мог сохранить их в сеансе.

Основная проблема, с которой я сталкиваюсь, заключается в том, что в правиле может содержаться либо «Карта», у которой просто есть лицо карты, либо «SuitedCard», которая наследует Карту, а также имеет костюм карты.

Поэтому, когда я сериализую, а затем десериализирую Список всех мастей-карт, превращающихся в карты (что приводит к исчезновению мастей карт), я предполагаю, что это модель по умолчанию.

Как бы это исправить? Есть ли что-то, что я могу добавить к расширению сеанса, которое помогает различать, или это безнадежное дело?

Прежде чем пытаться сделать это с подклассами, я пытался сделать то же самое, используя интерфейсы, но проблема в том, что расширение сеанса пытается создать экземпляр интерфейса, что вызывает ошибки.

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.

1 Ответ

0 голосов
/ 04 июня 2019

Вы пробовали

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

Это будет включать имена классов в Json, так что это поможет лучше идентифицировать типы во время десериализации.

...