2009-09-03 23 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的虛擬構造函數,你爲什麼要問?)