我一直在使用的一个应用程序在尝试序列化类型时失败了。

像这样的陈述

XmlSerializer lizer = new XmlSerializer(typeof(MyType));

生产:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)

我没有为我的类定义任何特殊的序列化器。

我该如何解决这个问题?


当前回答

我遇到了这个问题,上面提到的任何解决方案都无法解决它。

后来我终于找到了解决办法。 序列化器似乎不仅需要类型,还需要嵌套类型。 改变:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

为我修正了这个问题。 没有什么例外。

其他回答

Like Martin Sherburn said, this is normal behavior. The constructor of the XmlSerializer first tries to find an assembly named [YourAssembly].XmlSerializers.dll which should contain the generated class for serialization of your type. Since such a DLL has not been generated yet (they are not by default), a FileNotFoundException is thrown. When that happenes, XmlSerializer's constructor catches that exception, and the DLL is generated automatically at runtime by the XmlSerializer's constructor (this is done by generating C# source files in the %temp% directory of your computer, then compiling them using the C# compiler). Additional constructions of an XmlSerializer for the same type will just use the already generated DLL.

更新:从。net 4.5开始,XmlSerializer不再执行代码生成,也不再为了在运行时创建序列化程序集而使用c#编译器执行编译,除非通过设置配置文件设置(useLegacySerializerGeneration)显式强制执行。此更改消除了对csc.exe的依赖,并提高了启动性能。来源:. net Framework 4.5 Readme,章节1.3.8.1。

异常由XmlSerializer的构造函数处理。你不需要自己做任何事情,你可以点击“继续”(F5)继续执行你的程序,一切都会好的。如果你被异常停止程序执行并弹出异常助手所困扰,你要么关闭“只是我的代码”,要么将FileNotFoundException设置为在抛出时中断执行,而不是在“User-unhandled”时。

打开“Just My Code”,请转到“Tools >> Options >> Debugging >> General >> enable Just My Code”。要关闭FileNotFound被抛出时的执行中断,请转到调试>>异常>>找到>>输入'FileNotFoundException' >>取消System.IO.FileNotFoundException中的' thrown '复选框。

为了避免异常,你需要做两件事:

向序列化类添加属性(我希望您有访问权限) 使用sgen.exe生成序列化文件

将System.Xml.Serialization.XmlSerializerAssembly属性添加到类中。 将'MyAssembly'替换为MyClass所在程序集的名称。

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{
…
}

使用sgen.exe实用程序生成序列化文件,并将其与类的程序集一起部署。

' sgen.exe MyAssembly.dll '将生成文件myassembly . xmlserializer .dll

这两个更改将导致.net直接查找程序集。 我检查了一下,它在。net框架3.5和Visual Studio 2008上工作

有一个变通的办法。如果你使用

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

它应该避免这种异常。这对我很管用。

警告:不要多次使用,否则会出现内存泄漏

如果多次使用此方法为同一类型创建XmlSerializer实例,将会导致内存严重泄漏!

这是因为该方法绕过了内置缓存提供的XmlSerializer(type)和XmlSerializer(type, defaultNameSpace)构造函数(所有其他构造函数也绕过缓存)。

如果使用任何方法来创建XmlSerializer,而不是通过这两个构造函数,那么必须实现自己的缓存,否则会导致内存泄漏。

在我的一个。net标准dll中也有类似的问题。

我使用了Microsoft.XmlSerializer.Generator nuget,它可以在. net Core和. net Standard上预生成XmlSerializer。

我也有同样的问题,直到我使用第三方工具从XSD生成类,它工作了!我发现这个工具在类的顶部添加了一些额外的代码。当我把同样的代码添加到我原来的类的顶部时,它起作用了。以下是我添加的内容……

#pragma warning disable
namespace MyNamespace
{
  using System;
  using System.Diagnostics;
  using System.Xml.Serialization;
  using System.Collections;
  using System.Xml.Schema;
  using System.ComponentModel;
  using System.Xml;
  using System.Collections.Generic;

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
  [System.SerializableAttribute()]
  [System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
  public partial class MyClassName
  {
  ...