如何序列化Control等複雜類型對象

來源:互聯網
上載者:User

.NET Framework提供了將對象序列化和還原序列化的能力。利用這種機制,我們可以將對象執行個體的狀態儲存到儲存媒體上,也可以將對象從一個地方傳遞到另一個地方。

.NET Framework提供了一些用於序列化的類。一個是BinnaryFormatter,它使用二進位格式序列化對象。另一個是SoapFormatter,它使用soap格式(基於XML格式)序列化對象。還可以使用XMLSerializer將對象序列化成XML格式。然而這種序列化機制是有一定限制的,它只能序列化特定的對象。這些對象要麼是從MarshalByRefObject派生的對象,要麼是標記為Serializable的簡單類型對象。像System.Windows.Forms.Control這類複雜的對象就不能被支援。

今天我要介紹的是如何序列化System.Windows.Forms.Control這類複雜的對象。在介紹之前,我們先看看序列化和還原序列化的流程。

 

分離出複雜的邏輯,最簡單的邏輯只有兩步,第一步-序列化過程:將記憶體中的對象資料用XML格式的資料表示。第二步-還原序列化過程:構造一個新對象,並將XML格式表示的資料賦值給這個新的對象。這樣,原始對象和新構造的對象會有同樣的資料,即表示同一種狀態。

經常使用VS2005,VS2008等IDE的開發人員,特別是做過Design Time開發的開發人員可能會注意到,這個過程其實和IDE自動產生控制項代碼的過程相似。

在使用IDE的過程中,我們在Design環境中給Form拖一個TextBox控制項,IDE會在Design環境中建立一個TextBox控制項,並產生相關C#或者VB等格式的代碼。這個階段叫設計時(DesignTime)。這個過程類似我們剛才講到的第一步-序列化過程。而我們點擊啟動並執行時候,這些文字格式設定的代碼又會被編譯運行,根據編譯的代碼產生一個新TextBox控制項在Form上顯示。這個階段叫運行時(RunTime)。這個過程就類似我們剛才講到的第二步-還原序列化過程。可以看出來,IDE在DesignTime下是將控制項執行個體序化成C#或VB等代碼。而在RunTime下是將代碼編譯運行,產生新的控制項執行個體來保持DesignTime下設計的狀態與RunTime下顯示的狀態一致。事實上,這也是序列化和還原序列化的一種方式。

既然IDE的這個過程也是序列化和還原序列化的方式,那麼IDE是怎麼實現複雜控制項序列化和還原序列化的呢?這可能需要另外一篇文章才能講清楚,這裡暫不研究。不過我們可以知道,IDE是有能力做這件事情的。我們也可以利用IDE的這種能力,來實現複雜控制項的序列化和還原序列化。

下面這段代碼示範了如何利用IDE的這種能力序列化一個Object。

SaveObject
 1        /**//// <summary>
 2        ///   Saves the <see cref="T:Object"/> to the given stream.
 3        /// </summary>
 4        /// <param name="value">
 5        ///   The <see cref="T:Object"/> will be serialized to save.
 6        /// </param>
 7        /// <param name="stream">
 8        ///   The stream to which the <see cref="T:Object"/> will be serialized.
 9        /// </param>
10        public static void SaveObject(object value, Stream stream)
11        {
12            if (stream == null)
13            {
14                throw new ArgumentNullException();
15            }
16
17            using (DesignSurface designSurface = new DesignSurface())
18            {
19                designSurface.BeginLoad(new DefaultCodeDomDesignerLoader());
20                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
21
22                SerializationStore store = serializationService.CreateStore();
23                serializationService.Serialize(store, value);
24                store.Save(stream);
25            }
26        }
27

下面這段代碼示範了如何利用IDE的這種能力還原序列化一個Object。 

LoadObject
 1        /**//// <summary>
 2        ///   Loads a <see cref="T:Object"/> from the given stream.
 3        /// </summary>
 4        /// <param name="stream">
 5        ///   The stream from which to load the <see cref="T:Object"/>.
 6        /// </param>
 7        /// <returns>
 8        ///   The loaded <see cref="T:Object"/>.
 9        /// </returns>
10        public static object LoadObject(Stream stream)
11        {
12            if (stream == null)
13            {
14                throw new ArgumentNullException();
15            }
16
17            using (DesignSurface designSurface = new DesignSurface())
18            {
19                designSurface.BeginLoad(new DefaultCodeDomDesignerLoader());
20                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
21
22                SerializationStore store = serializationService.LoadStore(stream);
23                ICollection collection = serializationService.Deserialize(store);
24
25                foreach (IComponent associatedComponent in designSurface.ComponentContainer.Components)
26                {
27                    designSurface.ComponentContainer.Remove(associatedComponent);
28                }
29
30                IEnumerator enumerator = collection.GetEnumerator();
31                if (enumerator.MoveNext())
32                {
33                    return enumerator.Current;
34                }
35
36                return null;
37            }
38        }

利用IDE的這種能力,我們還可以做很多事情,比如深度複製控制項。有時候,我們需要複製一個複雜的控制項,然而辦法有限,要麼使用反射枚舉控制項所有欄位賦值,要麼給所有屬性一個一個賦值。而屬性之間的依賴關係,參考型別的屬性如何處理等都是難題。利用控制項序列化和還原序列化,可以輕鬆實現控制項的複製。再比如在RunTime下得到控制項的C#,VB等代碼,因為序列化的中間產物就是C#,VB等代碼,所以利用這個機制很容易實現。這些代碼我寫了一個類庫,需要的可以和我聯絡。代碼太多,在這裡就不貼了。

補充:現在我已經把原始碼上傳了。可以在這裡下載。

原創文章,轉載請註明出處。KevinShan Email:txhak@163.com。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.