NikFaraday
@NikFaraday
Student full-stack Developer

Какой лучший способ передать объект с приватными полями?

Этот вопрос вытекает из предыдущего моего вопроса. Возможно я где-то слабо уловил суть и прот@пил, по этому не ругайте :D

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

Поля используются для приватных массивов различных типов, в классе есть индексаторы и методы работы с этими массивами, т.е., действия напрямую осуществить нельзя. Эти приватные полям сохраняют некое микросостояние объекта

Свойства имеют public get и private set/init

В объекте (И его связанных объектах) нет публичного Конструктора. Все объекты собираются через реализацию паттерна Builder, который строит большой, сложный объект согласное некой стратегии (Реализация паттерна Strategy), выбранной перед созданием объекта

Проблема
Сейчас нужно сделать обмен этими объектами между несколькими клиентами. Работает всё по стандартному http (asp.net core web api). Исходя из предыдущего вопроса, я понял, что стандартными сериализаторами это сделать не получится, т.к. для них нужен открытый конструктор без параметров (Хотя бы), что не подходит по бизнес требования задачи. Тут остаётся вопрос в том, как передать такой security object?

P.s.:
Скорее всего, кто-то точно скажет:
- если объект можно передать, значит ты должен "засветить" все его "внутренности", значит не стоит бояться сделать публичный конструктор для десериализации

Вопрос тут больше не в том, что бы "светить" приватными полями, а в сохранении логики построения объектов (Точнее целой иерархии). Можно воспользоваться рефлексией (Как уже было сказано в предыдущем вопросе), но это не лучший способ писать такой сериализатор в ручную. По крайней мере, я пока пытаюсь найти другие способы
  • Вопрос задан
  • 306 просмотров
Решения вопроса 1
VoidVolker
@VoidVolker Куратор тега C#
Dark side eye. А у нас печеньки! А у вас?
Если на обоих концах у вас dotNet или на одном JS, то можно попробовать MemoryPack - он умеет работать с приватными полями. Но есть нюанс: он хочет partial класс и сам генерирует основной класс с нужными ему статическими полями. Ну и для передачи по сети можно архиватором упаковать с контрольной суммой.

spoiler

Небольшой класс для упрощения упаковки/распаковки - наследуем от этого класса целевой объект и через расширение вызываем методы упаковки/распаковки:
    /// <summary>
    /// Класс [де]сериализуемый MemoryPack
    /// <br />Необходим для добавления всем наследуемым классам метода сериализации через расширение
    /// <br />Наследование данного метода не работает из-за каста в целевой класс
    /// </summary>
    public class Packable { }

    /// <summary>
    /// Расширение для [де]сериализуемых классов MemoryPack
    /// </summary>
    public static class PackableExtension
    {
        /// <summary>
        /// Сериализовать класс в массив байтов
        /// </summary>
        /// <typeparam name="T">Целевой класс</typeparam>
        /// <param name="data">Объект целевого класса</param>
        /// <returns></returns>
        public static byte[] Pack<T>(this T data) where T : Packable
            => MemoryPackSerializer.Serialize(data);

        /// <summary>
        /// Десериализовать класс из массива байтов
        /// </summary>
        /// <typeparam name="T">Целевой класс</typeparam>
        /// <param name="data">Массив байт</param>
        /// <returns></returns>
        public static T Unpack<T>(this byte[] data) where T : Packable
            => MemoryPackSerializer.Deserialize<T>(data);
    }
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы