Как инициализация объекта происходит при десериализации двоичных объектов в Flex?

124
10

Суть того, что я хотел бы знать и сосредоточиться на понимании, - это подробная информация о том, как двоичная десериализация происходит в Flex 3. Когда вызывается конструктор, когда заданы свойства, являются частными членами сериализованы или все десериализация происходит на сеттерах и через них и т.д.? Мне сложно найти информацию об этом.


В приложении Flex 3 AIR у меня довольно сложный графический объект (просто связка объектов, ссылающихся друг на друга, вроде большой модели данных, за исключением немного более сложной), которую я сериализую в файл, используя один вызов на FileStream.writeObject и readObject на корневом объекте, который сериализует и десериализует весь граф объекта.


Я обнаружил, что мне всегда нужно иметь конструктор по умолчанию, иначе я получаю исключения на объектах при десериализации, если они являются частью массива ArrayCollection. Поэтому мне нужно было установить параметры конструктора или установить значения по умолчанию. У меня теперь есть много таких сеттеров в моих классах, например ниже, где mConnection накапливает некоторую информацию, необходимую ей через разные сеттеры, где, как и раньше, я все это упаковал в конструктор, поскольку вся информация действительно необходима для подключения к функции


class Client
{
private var mConnection:Connection;
public function get connection():Connection{ return mConnection; }

public var mUser:User;
public function get user():User { return mUser; }
public function set user(value:User):void
{
mUser = value;
mConnection.username = user.username;
mConnection.password = user.password;
}

private var mServer:Server;
public function get server():Server { return mServer;}
public function set server(value:Server):void
{
mServer = value;
mConnection.serverIP = value.serverIP;
}

public function Client()
{
mConnection = new Connection();
}
}

public class Server
{
[Bindable]
public var Clients:ClientsCollection = new ClientsCollection( );//contains Client type
private var mServerIP:String;
public function get serverIP():String { return mServerIP; }
public function set serverIP(value:String):void
{
mServerIP = value;
serverName = mServerIP;
}

public var serverName:String;

public function Server(serverIP:String = "")
{
this.serverIP = serverIP;
}
}


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


Когда я добавил сериализацию, я столкнулся с проблемой, что после десериализации mConnection иногда имеет пустую строку и иногда будет иметь IP-адрес, который был сериализован. Что, кажется, происходит, насколько я могу судить, заключается в том, что иногда объекты десериализуются в другом порядке, а затем объекты присваиваются свойствам в различном порядке. Итак, скажем, в то время, когда я сериализую графа объектов, у меня есть isntance клиента, со ссылкой на экземпляр сервера и соединения, и одна последовательность событий во время десериализации (всего один вызов readObject) может быть


    Соединение построено.
    Свойства подключения заданы с десериализованными значениями.
    Сервер построен с конструктором по умолчанию (имеет пустую строку для serverIP)
    Значения сервера десериализируются и устанавливаются через сеттеры, восстанавливая serverIP до "127.0.0.1" или как это было.
    Клиент построен
    Свойству клиентского сервера назначается ранее созданный экземпляр сервера, в результате чего значение параметра serverIP сервера соединения устанавливается через этот установщик.

В этом случае соединение имеет правильный IP-адрес сервера. Я думаю, что, по-видимому, случайным образом, иногда это происходит иногда, в результате чего connection serverIp является пустой строкой после завершения десериализации.


    Соединение построено.
    Свойства подключения заданы с десериализованными значениями.
    Клиент построен
    Сервер построен с конструктором по умолчанию (имеет пустую строку для serverIP)
    Свойству клиентского сервера присваивается ранее созданный экземпляр сервера, в результате чего значение connectionIP сервера соединения устанавливается в пустую строку через этот установщик.
    Значения сервера десериализуются и устанавливаются через сеттеры, восстанавливая serverIP до "127.0.0.1" или что бы это ни было.

Таким образом, соединение serverIP по-прежнему является пустой строкой, потому что сервер был назначен свойству клиента до того, как сервер был полностью инициализирован.

Я мог бы, вероятно, разрешить это, используя привязку, чтобы обновления к серверу на сервере привязаны к соединению, но я считаю, что свойства привязки довольно сложны (это очень просто в интерфейсе пользователя в mxml, потому что вы просто используете фигурные скобки синтаксис, но делать это по коду - это то, что я нашел сложным). Я также разрешил некоторые случаи, полностью удалив параметры конструктора, чтобы не было значений по умолчанию. Все это в стороне, мне по-прежнему нужно более глубокое понимание деталей бинарной сериализации, насколько оно перестраивает граф объектов. У меня даже есть круглые ссылки, и, похоже, они обрабатывают эти тонкие и поддерживают множественные ссылки без дублирования объектов. Это просто, когда мои конструкторы/сеттеры более сложны, и я сталкиваюсь с этими проблемами из-за порядка того, что происходит во время десериализации. Это действительно непоследовательно, поскольку добавление точек останова в разных местах, похоже, влияет на порядок вещей, что затрудняет отладку.


На стороне примечания для тех, кто может отвлечь тему, потому что я сериализую класс под названием Connection. Я добавил код для решения некоторых вопросов, например, в классе Connection есть экземпляр Socket. Конечно, мой сокет не будет подключен после того, как я закрою и снова открою приложение и десериализую его, поэтому, прежде чем я сериализую свой графический объект, я прохожу через и закрываю сокет и устанавливаю ссылку в классе Connection равным null, так что нет более длинная ссылка на сокет и, следовательно, не будет сериализована. После десериализации на следующем запуске приложения я создаю новый сокет.

спросил(а) 2021-01-25T19:32:25+03:00 4 месяца, 2 недели назад
1
Решение
63

Вид побочной заметки: вы можете использовать статическую функцию как псевдоперегруженный конструктор


class Fred
{
public function Fred()
{
// boring, default constructor with no parameters
}

public static function Freddy(aValue1 : String, aValue2 : Object = null) : Fred
{
var result : Fred = new Fred();

result.value1 = aValue1;
result.value2 = aValue2;

return result;
}
}

(Да, я пропускаю мои виртуальные конструкторы Object Pascal, почему вы спрашиваете?)

ответил(а) 2021-01-25T19:32:25+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема