我正在使用Microsoft Dynamics CRM进行一些实验。您通过Web服务与它进行交互,并且我已将Web引用添加到我的项目中。 Web服务接口非常丰富,生成的“Reference.cs”大约是90k loc。
我在控制台应用程序中使用Web引用。我经常改变一些东西,重新编译并运行。编译速度很快,但新增Web服务引用非常慢,大约需要15-20秒:
CrmService service = new CrmService();
分析显示所有时间都花在SoapHttpClientProtocol构造函数中。
显然,罪魁祸首是XML序列化代码(不包括在上面提到的90k loc中)是在运行时生成的,然后才进行JIT。这在构造函数调用期间发生。在玩耍和尝试时,等待是相当令人沮丧的。
我尝试了sgen.exe,ngen和XGenPlus的各种组合(需要几个小时才能生成500MB的额外代码),但无济于事。我已经考虑过实现一个几乎没有CrmService实例的Windows服务,可以在需要的时候发布,但这似乎太过分了。
有什么想法吗?
答案 0 :(得分:36)
答案 1 :(得分:1)
您可能希望查看.NET附带的Sgen.exe
工具。在Visual Studio的C#项目属性“Build”页面中,还有一个方便的小东西,在最底层,称为“构建序列化程序集”,它会自动为您运行Sgen
。
答案 2 :(得分:1)
我认为这不是一个SGEN问题。我已经查看了构造函数代码,我发现它正在进行大量的反射(基于类上的XmlIncludeAttribute)。它反映了所有这些,可能需要很长时间。
答案 3 :(得分:1)
CRM附带了预生成的XmlSerializer程序集。检查GAC中是否有SdkTypeProxy.XmlSerializers.dll和SdkProxy.XmlSerializers.dll。
如果不这样,那意味着当您创建CrmService时,.net将生成XmlSerializer程序集,这可能需要一些时间。 希望这有帮助
答案 4 :(得分:0)
我试图找出为什么我的初始SoapHttpClientProtocol
电话花了这么长时间,我遇到了这个帖子。
我发现将Proxy设置为null / Empty会停止Proxy AutoDetect的发生 - 这在初始调用时最多需要7秒钟:
this.Proxy = GlobalProxySelection.GetEmptyWebProxy();
答案 5 :(得分:0)
我已经使用了上面详细的答案作为指导,并向前迈了几步,制作了一个自动化流程的脚本。脚本由两个文件组成:
generateproxy.bat:
REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin
wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll
generateproxy.ps1
(Get-Content VIM.cs) |
ForEach-Object {
$_ -replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" `
-replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" `
-replace "using System;", "namespace Classes.WS_VIM { `n`nusing System;"
} |
Set-Content VIM.cs
Add-Content VIM.cs "`n}"
我已将这两个文件添加到客户端项目中,并且在预构建事件中我添加了行
cd..\..
generateproxy
因此,在每次构建之前,代理类都会重新生成,而开发人员(几乎)不需要考虑它。构建时,WS必须启动并运行,其URL必须在bat文件中。作为预构建的结果,两个dll文件将在客户端项目的子文件夹引用中重新生成。 首次执行脚本后,您应该添加对新dll的引用。