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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/134224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:59:42  来源:igfitidea点击:

Generating an Xml Serialization assembly as part of my build

提问by Adam Tegen

This code produces a FileNotFoundException, but ultimately runs without issue:

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

void ReadXml()
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    //...
}

Here is the exception:

这是例外:



A first chance exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll

mscorlib.dll 中发生了“System.IO.FileNotFoundException”类型的第一次机会异常

Additional information: Could not load file or assembly 'MyAssembly.XmlSerializers, Version=1.4.3190.15950, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

附加信息:无法加载文件或程序集“MyAssembly.XmlSerializers, Version=1.4.3190.15950, Culture=neutral, PublicKeyToken=null”或其依赖项之一。该系统找不到指定的文件。



It appears that the framework automatically generates the serialization assembly if it isn't found.I can generate it manually using sgen.exe, which alleviates the exception.

如果找不到,框架似乎会自动生成序列化程序集。我可以使用 sgen.exe 手动生成它,这可以缓解异常。

How do I get visual studio to generate the XML Serialization assembly automatically?

如何让 Visual Studio 自动生成 XML 序列化程序集?



Update: The Generate Serialization Assembly: On setting doesn't appear to do anything.

更新:Generate Serialization Assembly: On 设置似乎没有做任何事情。

采纳答案by flipdoubt

This is how I managed to do it by modifying the MSBUILD script in my .CSPROJ file:

这是我通过修改 .CSPROJ 文件中的 MSBUILD 脚本设法做到的:

First, open your .CSPROJ file as a file rather than as a project. Scroll to the bottom of the file until you find this commented out code, just before the close of the Project tag:

首先,将 .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>
-->

Now we just insert our own AfterBuild target to delete any existing XmlSerializer and SGen our own, like so:

现在我们只需插入我们自己的 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>

That works for me.

这对我行得通。

回答by Darren Kopp

Look in the properties on the solution. On the build tab at the bottom there is a dropdown called "Generate Serialization assembly"

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

回答by Martin Hollingsworth

The other answers to this question have already mentioned the Project Properties->Build->Generate Serialization Assembliessetting but by default this will only generate the assembly if there are "XML Web service proxy types" in the project.

这个问题的其他答案已经提到了 Project Properties->Build-> Generate Serialization Assemblies设置,但默认情况下,如果项目中有“ XML Web 服务代理类型”,这只会生成程序集。

The best way to understand the exact behaviour of Visual Studio is to to examine the GenerateSerializationAssembliestarget within the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727**Microsoft.Common.targets** file.

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

You can check the result of this build task from the Visual Studio Outputwindow and select Buildfrom the Show output from: drop down box. You should see something along the lines of

您可以从 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 -> D:\Temp\LibraryA\bin\Debug\LibraryA.dll

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 -> D:\Temp\LibraryA\bin\Debug\LibraryA.dll

The key point here is the /proxytypesswitch. You can read about the various switches for the XML Serializer Generator Tool (Sgen.exe)

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

If you are familiar with MSBuild you could customise the GenerateSerializationAssemblies target so that SGen task has an attribute of UseProxyTypes="false" instead of true but then you need to take on board all of the associated responsibility of customising the Visual Studio / MSBuild system. Alternatively you could just extend your build process to call SGen manually without the /proxytypes switch.

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

If you read the documentation for SGen they are fairly clear that Microsoft wanted to limit the use of this facility. Given the amount of noise on this topic, it's pretty clear that Microsoft did not do a great job with documenting the Visual Studio experience. There is even a Connect Feedbackitem for this issue and the response is not great.

如果您阅读了 SGen 的文档,他们会很清楚 Microsoft 想要限制此功能的使用。考虑到有关此主题的大量噪音,很明显 Microsoft 在记录 Visual Studio 体验方面做得并不好。甚至有针对此问题的Connect Feedback项,但响应并不好。

回答by joniba

In case someone else runs into this problem suddenly after everything was working fine before: For me it had to do with the "Enable Just My Code (Managed Only)" checkbox being unchecked in the options menu (Options -> Debugging) (which was automatically switched off after installing .NET Reflector).

万一其他人在之前一切正常后突然遇到这个问题:对我来说,这与在选项菜单(选项 - > 调试)(这是安装 .NET Reflector 后自动关闭)。

EDIT: Which is to say, of course, that this exception was happening before, but when "enable just my code" is off, the debugging assistant (if enabled), will stop at this point when thrown.

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

回答by heavyd

As Martin has explained in his answer, turning on generation of the serialization assembly through the project properties is not enough because the SGen task is adding the /proxytypesswitch to the sgen.exe command line.

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

Microsoft has a documented MSBuild propertywhich allows you to disable the /proxytypesswitch and causes the SGen Task to generate the serialization assemblies even if there are no proxy types in the assembly.

Microsoft 有一个文档化的 MSBuild 属性,它允许您禁用/proxytypes开关并导致 SGen 任务生成序列化程序集,即使程序集中没有代理类型也是如此。

SGenUseProxyTypes

A boolean value that indicates whether proxy types should be generated by SGen.exe. The SGen target uses this property to set the UseProxyTypes flag. This property defaults to true, and there is no UI to change this. To generate the serialization assembly for non-webservice types, add this property to the project file and set it to false before importing the Microsoft.Common.Targets or the C#/VB.targets

SGenUseProxyTypes

一个布尔值,指示代理类型是否应由 SGen.exe 生成。SGen 目标使用此属性来设置 UseProxyTypes 标志。此属性默认为 true,并且没有 UI 可以更改此设置。要为非 webservice 类型生成序列化程序集,请在导入 Microsoft.Common.Targets 或 C#/VB.targets 之前将此属性添加到项目文件并将其设置为 false

As the documentation suggests you must modify your project file by hand, but you can add the SGenUseProxyTypesproperty to your configuration to enable generation. Your project files configuration would end up looking something like this:

正如文档所建议的,您必须手动修改您的项目文件,但您可以将该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>

回答by brain backup

creating a new sgen task definition breaks a fly on the wheel. just set the needed variables to make the task work as intended. Anyway the microsoft documentation lacks some important info.

创建一个新的 sgen 任务定义打破了车轮上的苍蝇。只需设置所需的变量即可使任务按预期工作。无论如何,微软文档缺少一些重要信息。

Steps to pre-generate serialization assemblies

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

(with parts from http://msdn.microsoft.com/en-us/library/ff798449.aspx)

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

  1. In Visual Studio 2010, in Solution Explorer, right-click the project for which you want to generate serialization assemblies, and then click Unload Project.
  2. In Solution Explorer, right-click the project for which you want to generate serialization assemblies, and then click Edit .csproj.
  3. In the .csproj file, immediately after the <TargetFrameworkVersion>v?.?</TargetFrameworkVersion>element, add the following elements:

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

  4. In the .csproj file, in each platform configuration

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

    add the following line:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. Save and close the .csproj file.

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

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

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

    例如 <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    添加以下行:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

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

  6. 在解决方案资源管理器中,右键单击您刚刚编辑的项目,然后单击重新加载项目。

This procedure generates an additional assembly named .xmlSerializers.dll in your output folder. You will need to deploy this assembly with your solution.

此过程会在您的输出文件夹中生成一个名为 .xmlSerializers.dll 的附加程序集。您将需要使用您的解决方案部署此程序集。



Explanation

解释

SGen by default only for proxy types generates for “Any CPU”. This happens if you don't set the according variables in your project file.

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

SGenPlatformTarget is required to match your PlatformTarget. I tend to think this is a bug in the project template. Why should the sgen target platform differ from your project's? If it does you will get a runtime exception

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

0x80131040: The located assembly's manifest definition does not match the assembly reference

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

You can locate the msbuild task definition by analyzing your project file:

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

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

where MSBuildToolsPath depends on your <TargetFrameworkVersion>http://msdn.microsoft.com/en-us/library/bb397428.aspx

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

Look inside the SGen task definition for TargetFrameworkVersion 4.0 from

从以下位置查看 TargetFrameworkVersion 4.0 的 SGen 任务定义

Windows installation path\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets

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

to see the undocumented variables like $(SGenPlatformTarget) you are free to set in your project file

查看未记录的变量,如 $(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>

回答by Timoty Weis

A slightly different solution from the one provided by brain backupcould be to directly specify the platform target right where you have to use it like so:

大脑备份提供的解决方案略有不同的解决方案可能是直接指定平台目标,您必须像这样使用它:

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

回答by mcfea

I'm a little late to the party, but I found the previous answer difficult to work with. Specifically Visual Studio would crash whenever I tried to view the properties of my project. I figure this was due to the fact that it no longer understood how to read the csproj file. That said...

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

Add the following to your post-build event command line:

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

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

This will leverage sgen.exe directly to rebuild the Xml Serialization assembly every time you build your project for Debug or Release.

每次为调试或发布构建项目时,这将直接利用 sgen.exe 重新构建 Xml 序列化程序集。