Sgen.exe: Speed up XmlSerializer's Startup Performance [.NET 2.0, XML Serialization]
?
Written by Allen Lee
?
1. Why Sgen.exe?
在《Serialize Your Deck with Positron [XML Serialization, XSD, C#]》一文中,我們領略到 XML Serialization 是如何簡化我們的 XML 處理工作。然而,XmlSerializer 在每次運行應用程序時,都會為待處理的類型生成用于序列化的代碼和程序集(assembly),這就導致了一個性能問題。
.NET 2.0 引入了 Sgen.exe 這個小工具,你可以用它為你的類預先生成那些用于序列化的程序集,讓這些程序集隨你的類一同發布,并使用這些程序集里面的 Serializer(s) 來對你的類執行序列化操作。
注意:本文將使用《Serialize Your Deck with Positron [XML Serialization, XSD, C#]》中的 Cards.cs 作為原始材料。
?
2. How to ...
2.1 ... Create a Serializer for Cards?
Step #01:把 Cards.cs 編譯為 Positron.Core.dll。
Step #02:啟動 SDK Command Prompt,去到 Positron.Core.dll 所在的目錄并輸入
sgen Positron.Core.dll
然后按下 [Enter],Sgen.exe 會在當前的目錄中生成一個 Positron.Core.XmlSerializers.dll 文件,它就是我們將用來提速的武器了。
至此,用于 Cards 的序列化的程序集已經制作完畢了。如果你想查看 Sgen.exe 究竟生成了什么代碼,一個眾所周知的方法就是使用 Reflector。但這里有一個更加簡單直接的方法,就是使用 Sgen.exe 所提供的 /k 或者 /keep 參數,該參數通知 Sgen.exe 把所生成的 C# 代碼保留在當前目錄中。
2.2 ... Use the Serializer in Cards?
Step #01:在 Visual C# 2005 Express Edition Beta 的 Solution Explorer 中添加對 Positron.Core.XmlSerializers.dll 的引用。
Step #02:在 Cards.cs 上添加如下語句:

Step #03:修改 Cards.Load 和 Cards.Save 的實現,我們需要做的僅僅是把原來的

換成

至此,我們已經完成了對 Cards.cs 的改造了。
?
3. What's More...
如果你查看 Sgen.exe 所生成的代碼,無論你通過何種方式,你將發現里面有一系列以類名作為前綴的 Serializer,隨便哪個都可以單獨使用,但在 Positron 中,單獨使用別的 Serializer 是沒意義,因為我們不單獨序列化某個子元素或者屬性。
除此之外,里面的 XmlSerializerContract 也是一個有趣的類。默認情況下,Sgen.exe 會試圖為你所指定的輸入程序集中的每一個類生成一個 Serializer,但事實上并不是所有的類都能生成 Serializer,那么你如何得知 Sgen.exe 是否為輸入程序集中的某個類生成了一個 Serializer 呢?答案就在 XmlSerializerContract.CanSerialize 方法中,把你想測試的類型作為參數傳遞給該方法,如果 Sgen.exe 所生成的程序集包含該類型的 Serializer,該方法就返回 true,否則返回 false。另外,如果 Sgen.exe 所生成的程序集中包含較多的 Serializer,并且每個 Serializer 單獨使用都有意義,那么 XmlSerializerContract 可以作為一個工廠使用,把你希望序列化的類型作為參數傳遞給 XmlSerializerContract.GetSerializer,它將返回該類型的 Serializer,當然,前提是有這樣一個 Serializer。