以下内容来自VMWare 论坛上的此线程:
嗨伙计,
我们发现 sgen.exe 确实有效。只是除了预生成我们在这个线程中遗漏的序列化程序 dll 之外,还有几个额外的步骤。这是详细说明
问题
当从 .NET 使用 VIM 2.0 SDK 时,需要很长时间来实例化 VimService 类。(VimService类是运行'wsdl.exe vim.wsdl vimService.wsdl'生成的代理类)
换句话说,以下代码行:
_service = new VimService();
执行可能需要大约 50 秒。
原因
显然,.NETXmlSerializer
使用System.Xml.Serialization.*
注释代理类的属性在运行时生成序列化代码。当代理类很多且很大时,如 VimService.cs 中的代码,序列化代码的生成可能需要很长时间。
解决方案
这是 Microsoft .NET 序列化程序工作方式的一个已知问题。
以下是 MSDN 提供的有关解决此问题的一些参考资料:
http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx
http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx
不幸的是,以上参考资料都没有描述该问题的完整解决方案。相反,他们专注于如何预先生成 XML 序列化代码。
完整的修复涉及以下步骤:
使用预生成的 XML 序列化程序代码创建程序集(DLL)
从代理代码中删除所有对 System.Xml.Serialization.* 属性的引用(即从 VimService.cs 文件中)
使用 XmlSerializerAssemblyAttribute 注释主代理类,以将其指向 XML 序列化程序程序集所在的位置。
跳过第 2 步只会导致VimService
类的实例化时间缩短 20%。跳过第 1 步或第 3 步会导致代码不正确。通过所有三个步骤,实现了 98% 的改进。
以下是分步说明:
在开始之前,请确保您使用的是 .NET 版本 2.0 工具。此解决方案不适用于 .NET 1.1 版,因为 sgen 工具和XmlSerializationAssemblyAttribute
仅在 .NET 2.0 版中可用
使用 wsdl.exe 从 WSDL 生成 VimService.cs 文件:
wsdl.exe vim.wsdl vimService.wsdl
这将输出当前目录下的 VimService.cs 文件
将 VimService.cs 编译成库
csc /t:library /out:VimService.dll VimService.cs
使用 sgen 工具预生成和编译 XML 序列化程序:
sgen /p VimService.dll
这将输出当前目录中的 VimService.XmlSerializers.dll
返回到 VimService.cs 文件并删除所有System.Xml.Serialization.*
属性。因为代码代码很大,最好的方法是使用一些正则表达式替换工具。执行此操作时要小心,因为并非所有属性都单独出现在一行上。有些是作为方法声明的一部分内联的。
如果您觉得这一步很困难,这里有一个简化的方法:
假设您正在编写 C#,请对以下字符串进行全局替换:
[System.Xml.Serialization.XmlIncludeAttribute
并将其替换为:
// [System.Xml.Serialization.XmlIncludeAttribute
这将通过将Xml.Serialization
它们注释掉来摆脱那些是导致减速的最大罪魁祸首的属性。如果您使用的是其他 .NET 语言,只需根据该语言的语法将替换的字符串修改为前缀注释即可。这种简化的方法将使您获得最大的加速。删除其余的 Xml.Serialization 属性只能实现额外的 0.2 秒加速。
在 VimService.cs 中的 VimService 类中添加以下属性:
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
你应该得到这样的结果:
// ... Some code here ...
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol {
// ... More code here
通过重新生成 VimSerice.dll 库
csc /t:library /out:VimService.dll VimService.cs
现在,从您的应用程序中,您可以添加对 VimSerice.dll 库的引用。
运行您的应用程序并验证 VimService 对象实例化时间是否减少。
补充笔记
sgen 工具有点像一个黑盒子,它的行为会根据您在 Machine.config 文件中的内容而有所不同。例如,默认情况下,它应该输出优化的非调试代码,但并非总是如此。要了解该工具,请在步骤 3 中使用 /k 标志,这将导致它保留所有临时生成的文件,包括它生成的源文件和命令行选项文件。
即使经过上述修复,第一次实例化 VimService 类所需的时间也不是瞬时的(1.5 秒)。根据经验观察,剩余时间的大部分似乎是由于处理SoapDocumentMethodAttribute
属性。目前尚不清楚如何减少此时间。预生成的 XmlSerializer 程序集不考虑与 SOAP 相关的属性,因此这些属性需要保留在代码中。好消息是该应用程序的 VimService 类的第一次实例化需要很长时间。因此,如果额外的 1.5 秒有问题,可以尝试在应用程序开始时对此类进行虚拟实例化,以改善登录时间的用户体验。