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。