生成Xml序列化程序集作为构建的一部分

时间:2008-09-25 16:06:17

标签: c# xml xml-serialization

此代码产生FileNotFoundException,但最终运行没有问题:

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序列化程序集?


更新:生成序列化程序集:打开设置似乎没有做任何事情。

8 个答案:

答案 0 :(得分:67)

正如Martin在his answer中解释的那样,通过项目属性启用序列化程序集的生成是不够的,因为SGen任务正在将/proxytypes开关添加到sgen.exe命令行。 / p>

Microsoft有documented MSBuild property,允许您禁用/proxytypes开关,并使SGen Task生成序列化程序集,即使程序集中没有代理类型也是如此。

  

SGenUseProxyTypes

     

一个布尔值,指示是否代理类型   应该由SGen.exe生成。 SGen目标使用此属性   设置UseProxyTypes标志。此属性默认为true,并且存在   没有UI可以改变它。生成序列化程序集   非Web服务类型,将此属性添加到项目文件并进行设置   导入Microsoft.Common.Targets或之前为false   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>

答案 1 :(得分:56)

这是我通过修改.CSPROJ文件中的MSBUILD脚本来实现这一目的的方法:

首先,将.CSPROJ文件作为文件而不是项目打开。滚动到文件的底部,直到找到这个注释掉的代码,就在Project标签关闭之前:

<!-- 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>
-->

现在我们只是插入我们自己的AfterBuild目标来删除任何现有的XmlSerializer和我们自己的SGen,如下所示:

<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>

这适合我。

答案 2 :(得分:29)

此问题的其他答案已经提到了项目属性 - >构建 - > 生成序列化程序集设置,但默认情况下,如果存在“ XML,则只生成程序集项目中的Web服务代理类型“。

了解Visual Studio的确切行为的最佳方法是检查C:\ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 ** Microsoft.Common中的 GenerateSerializationAssemblies 目标。目标**文件。

您可以从Visual Studio 输出窗口检查此构建任务的结果,然后从显示输出>下拉列表中选择构建:框。您应该看到

的内容

C:\ Program Files \ Microsoft Visual Studio 8 \ SDK \ v2.0 \ bin \ sgen.exe /assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll / proxytypes / reference:.. / compiler:/ delaysign- LibraryA - &gt; d:\ TEMP \ LibraryA的\ BIN \调试\ LibraryA.dll

这里的关键点是/ proxytypes 开关。您可以阅读XML Serializer Generator Tool (Sgen.exe)

的各种开关

如果您熟悉MSBuild,则可以自定义GenerateSerializationAssemblies目标,以便SGen任务具有UseProxyTypes =“false”属性而不是true但是 那么你需要承担定制Visual Studio / MSBuild系统的所有相关责任。或者,您可以扩展构建过程以手动调用SGen而无需/ proxytypes开关。

如果您阅读了SGen的文档,他们很清楚Microsoft希望限制此工具的使用。考虑到这个主题的噪音量,很明显微软在记录Visual Studio体验方面做得并不好。此问题甚至有一个Connect Feedback项,响应也不是很好。

答案 3 :(得分:9)

创建一个新的sgen任务定义会打破方向盘上的一个飞行。只需设置所需的变量,使任务按预期工作。无论如何,微软文档缺少一些重要的信息。

预生成序列化程序集的步骤

(部分来自http://msdn.microsoft.com/en-us/library/ff798449.aspx

  1. 在Visual Studio 2010中,在“解决方案资源管理器”中,右键单击要为其生成序列化程序集的项目,然后单击“卸载项目”。
  2. 在“解决方案资源管理器”中,右键单击要为其生成序列化程序集的项目,然后单击“编辑.csproj”。
  3. 在.csproj文件中,紧跟<TargetFrameworkVersion>v?.?</TargetFrameworkVersion>元素之后,添加以下元素:

      

    <SGenUseProxyTypes>false</SGenUseProxyTypes>   <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. 在.csproj文件中,在每个平台配置中

    e.g。 <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    添加以下行:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. 保存并关闭.csproj文件。

  6. 在“解决方案资源管理器”中,右键单击刚编辑的项目,然后单击“重新加载项目”。
  7. 此过程在输出文件夹中生成一个名为.xmlSerializers.dll的附加程序集。您需要使用您的解决方案部署此程序集。


    说明

    默认情况下,SGen仅为“任何CPU”生成代理类型。如果未在项目文件中设置相应变量,则会发生这种情况。

    需要使用SGenPlatformTarget来匹配您的PlatformTarget。我倾向于认为这是项目模板中的一个错误。为什么sgen目标平台与您的项目不同?如果是,您将获得运行时异常

      

    0x80131040:定位的程序集的清单定义与程序集引用

    不匹配

    您可以通过分析项目文件来找到msbuild任务定义:

    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
    

    MSBuildToolsPath取决于您的<TargetFrameworkVersion> http://msdn.microsoft.com/en-us/library/bb397428.aspx

    中查看TargetFrameworkVersion 4.0的SGen任务定义
      

    Windows安装路径\ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.CSharp.targets

    查看$(SGenPlatformTarget)等未记录的变量,您可以在项目文件中自由设置

    <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>
    

答案 4 :(得分:2)

如果其他人在之前一切正常工作之后突然遇到此问题:对我而言,它与选项菜单中未选中的“仅启用我的代码(仅管理)”复选框有关(选项 - &gt;调试)(安装.NET Reflector后自动关闭)。

编辑: 也就是说,当然,之前发生过这种异常,但是当“启用我的代码”关闭时,调试助手(如果启用)将在抛出此时停止。

答案 5 :(得分:2)

我参加派对有点晚了,但我发现之前的答案难以解决。每当我尝试查看项目的属性时,Visual Studio都会崩溃。我认为这是因为它不再理解如何读取csproj文件。那说......

将以下内容添加到构建后事件命令行:

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force

每次为Debug或Release构建项目时,这将直接利用sgen.exe重建Xml Serialization程序集。

答案 6 :(得分:1)

查看解决方案的属性。在底部的构建选项卡上有一个名为“生成序列化程序集”的下拉列表

答案 7 :(得分:1)

brain backup提供的解决方案略有不同的解决方案可能是直接指定平台目标,您必须使用它,如下所示:

<!-- 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>