C# 生成Xml序列化程序集作为生成的一部分
此代码生成FileNotFoundException,但最终运行时不会出现问题:C# 生成Xml序列化程序集作为生成的一部分,c#,xml,xml-serialization,C#,Xml,Xml Serialization,此代码生成FileNotFoundException,但最终运行时不会出现问题: void ReadXml() { XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); //... } 例外情况如下: mscorlib.dll中发生“System.IO.FileNotFoundException”类型的第一次意外异常 其他信息:无法加载文件或程序集“MyAssembly.XmlSerializers,Ve
void ReadXml()
{
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
//...
}
例外情况如下:
mscorlib.dll中发生“System.IO.FileNotFoundException”类型的第一次意外异常 其他信息:无法加载文件或程序集“MyAssembly.XmlSerializers,Version=1.4.3190.15950,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件
如果找不到序列化程序集,框架似乎会自动生成该程序集。我可以使用sgen.exe手动生成该程序集,从而缓解异常情况 如何让visual studio自动生成XML序列化程序集?
更新:Generate Serialization Assembly:On设置似乎没有任何作用。查看解决方案的属性。在底部的build选项卡上有一个名为“Generate Serialization assembly”的下拉列表,这是我通过修改.CSPROJ文件中的MSBUILD脚本来实现的: 首先,将.CSPROJ文件作为文件而不是项目打开。滚动到文件底部,直到在项目标记关闭之前找到注释掉的代码:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
现在,我们只需插入我们自己的后构建目标来删除任何现有的XmlSerializer,然后生成我们自己的XmlSerializer,如下所示:
<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete
Files="$(TargetDir)$(TargetName).XmlSerializers.dll"
ContinueOnError="true" />
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(OutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="true"
UseProxyTypes="false"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(TargetFrameworkSDKToolsDirectory)"
Platform="$(Platform)">
<Output
TaskParameter="SerializationAssembly"
ItemName="SerializationAssembly" />
</SGen>
</Target>
这对我很有用。这个问题的其他答案已经提到了项目属性->构建->生成序列化程序集设置,但默认情况下,只有在项目中存在“XML Web服务代理类型”时,才会生成程序集 了解Visual Studio确切行为的最佳方法是检查C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727**Microsoft.Common.targets**文件中的GenerateSerializationAssemblys目标 您可以从Visual Studio的“输出”窗口检查此生成任务的结果,并从“显示从输出”下拉框中选择“生成”。你应该看到一些类似的东西 C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\sgen.exe/assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll/proxytypes/参考:/编译器:/delaysign- LibraryA->D:\Temp\LibraryA\bin\Debug\LibraryA.dll 这里的关键点是/proxytypes开关。您可以阅读关于的各种开关 如果熟悉MSBuild,可以自定义GenerateSerializationAssemblys目标,以便SGen任务的属性为UseProxyTypes=“false”,而不是true,但 然后,您需要承担定制VisualStudio/MSBuild系统的所有相关责任。或者,您可以扩展构建过程,在不使用/proxytypes开关的情况下手动调用SGen
如果您阅读了SGen的文档,他们很清楚Microsoft希望限制此功能的使用。考虑到这个话题的喧嚣程度,很明显微软在记录VisualStudio体验方面做得并不好。这个问题甚至有一个条目,但响应不是很好。如果以前一切正常后,其他人突然遇到这个问题:对我来说,这与“选项”菜单(选项->调试)中未选中“仅启用我的代码(仅管理)”复选框有关(安装.NET Reflector后自动关闭) 编辑:
当然,也就是说,这个异常以前发生过,但是当“仅启用我的代码”处于禁用状态时,调试助手(如果已启用),将在抛出时在此点停止。正如Martin在中所解释的,通过项目属性启用序列化程序集的生成是不够的,因为SGen任务正在将
/proxytypes
开关添加到SGen.exe命令行
Microsoft有一个允许您禁用/proxytypes
开关并使SGen任务生成序列化程序集,即使程序集中没有代理类型
Sgenuseproxitypes
一个布尔值,指示代理类型是否为
应该由SGen.exe生成。SGen目标使用此属性
设置UseProxyTypes标志。此属性默认为true,并且
没有可更改此的UI。若要为生成序列化程序集
非webservice类型,将此属性添加到项目文件并设置它
在导入Microsoft.Common.Targets或
C#/VB.targets
如文档所示,您必须手动修改项目文件,但您可以将SGenUseProxyTypes
属性添加到配置中以启用生成。您的项目文件配置最终将显示如下内容:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<!-- Snip... -->
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<SGenUseProxyTypes>false</SGenUseProxyTypes>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<!-- Snip... -->
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<SGenUseProxyTypes>false</SGenUseProxyTypes>
</PropertyGroup>
在…上
假的
在…上
假的
创建一个新的sgen任务定义打破了僵局。只需设置所需的变量即可使任务按预期工作。无论如何,microsoft文档缺少一些重要信息
预生成序列化程序集的步骤
(零件来自)
v?
元素之后添加以下元素:
false
$(平台)
添加follo
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target
Name="GenerateSerializationAssemblies"
Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
Outputs="$(IntermediateOutputPath)$(_SGenDllName)">
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(IntermediateOutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
UseProxyTypes="$(SGenUseProxyTypes)"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(SGenToolPath)"
SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
EnvironmentVariables="$(SGenEnvironment)"
SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
Platform="$(SGenPlatformTarget)"
Types="$(SGenSerializationTypes)">
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
</SGen>
</Target>
<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition=" '$(PlatformTarget)'=='' ">
<SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(PlatformTarget)'!='' ">
<SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>
<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(OutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="true"
UseProxyTypes="false"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(SGenToolPath)"
SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
EnvironmentVariables="$(SGenEnvironment)"
Platform="$(SGenPlatform)">
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force