2009-09-03 54 views
7

的想什么我知道,专注于了解的JIST,是如何反序列化的二进制在Flex 3中发生的细节。当被称为构造函数,当属性设置,是私有成员序列化或将完成所有发生的反序列化通过安装人员等?我很难找到关于此的信息。在一个Flex 3 AIR应用程序中,我有一个相当复杂的对象图(只是一堆相互引用的对象,有点像大数据模型,除了更复杂一点),我使用单个调用序列化为一个文件对根对象上的FileStream.writeObject和readObject进行序列化和反序列化整个对象图。在Flex中反序列化二进制对象时,对象初始化是如何发生的?

我发现我需要始终有一个默认的构造函数,否则,如果他们是一个ArrayCollection的一部分,我会反序列化时,得到的对象例外。所以我必须重新构造参数或设置默认值。我现在在我的类中有很多这样的setter,比如下面的mConnection通过不同的setter累积它需要的一些信息,因为之前我把这些全部打包到构造函数中,因为所有的信息对于Connection来说都是非常必要的:

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单个呼叫)过程中的事件一个序列的实例的引用可能:

  1. 连接构造。
  2. Connection的属性设置为反序列化的值。
  3. 服务器使用默认构造函数构造(对于serverIP具有空字符串)
  4. 服务器值是deserilized,并通过setter进行设置,将serverIP恢复为“127.0.0.1”或其它任何东西。
  5. 客户端被构建
  6. 客户端的服务器属性被分配以前构建的服务器实例,导致连接的serverIP值通过该设置者被设置。

在这种情况下,连接有正确的服务器IP。我认为,看起来是随机的,但是有时候会发生下面的情况,导致连接的serverIp在反序列化完成后成为空字符串。

  1. 连接构造。
  2. Connection的属性设置为反序列化的值。
  3. 客户构建
  4. 服务器构建了默认的构造函数(对服务器IP空字符串)
  5. 客户端的服务器属性分配与之前建构的服务器实例,从而导致连接的服务器IP值设置为一个空字符串通过这个setter。
  6. 服务器值被反序列化并通过setter进行设置,将serverIP恢复到“127.0.0.1”或其它任何东西。

所以连接的服务器IP仍然是一个空字符串,因为服务器被分配给客户端所拥有的服务器之前完全初始化。

我可以通过使用绑定来解决此问题,以便服务器中的serverip更新绑定到连接,但我发现绑定属性相当复杂(它在mxml中的UI上非常简单,因为您只是使用卷曲括号语法,但通过代码来做是我发现很复杂的)。我也通过完全删除构造函数参数解决了一些情况,所以没有默认值。除此之外,就其重建对象图而言,我仍然需要更深入地了解二进制序列化的细节。我甚至有循环引用,它似乎处理那些罚款和维护多个引用而不重复的对象。就在我的构造函数/设置者更复杂时,由于反序列化过程中出现的顺序,我遇到了这些问题。但它确实不一致,因为在各个地方添加断点似乎会影响事件发生的顺序,使其更难以调试。

在任何人可能偏离主题,因为我序列化一个称为连接类的一个侧面说明。我添加了一些代码来解决一些问题,比如在Connection类中有一个Socket实例。当然,我关闭并重新打开应用程序并将其反序列化后,我的套接字将无法连接,因此在序列化对象图之前,我会先关闭套接字并将Connection类中的引用设置为null,以便不存在对套接字的引用更长,因此它不会被序列化。在下一次应用程序运行后,我创建一个新的套接字。

回答

1

排序一个侧面说明的:你可以使用一个静态函数作为伪重载的构造

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的虚拟构造函数,你为什么要问?)