C# XmlSerializer 在构造函数中给出 FileNotFoundException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1127431/
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
XmlSerializer giving FileNotFoundException at constructor
提问by Irwin
An application I've been working with is failing when I try to serialize types.
当我尝试序列化类型时,我一直在使用的应用程序失败。
A statement like
像这样的声明
XmlSerializer lizer = new XmlSerializer(typeof(MyType));
produces:
产生:
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)
I don't define any special serializers for my class.
我没有为我的班级定义任何特殊的序列化程序。
How can I fix this problem?
我该如何解决这个问题?
采纳答案by Martin Sherburn
Believe it or not, this is normal behaviour. An exception is thrown but handled by the XmlSerializer, so if you just ignore it everything should continue on fine.
信不信由你,这是正常的行为。一个异常被抛出但由 XmlSerializer 处理,所以如果你只是忽略它,一切都应该继续正常。
I have found this very annoying, and there have been many complaints about this if you search around a bit, but from what I've read Microsoft don't plan on doing anything about it.
我发现这很烦人,如果您稍微搜索一下,就会有很多关于此的抱怨,但从我读到的内容来看,Microsoft 不打算对此做任何事情。
You can avoid getting Exception popups all the time while debugging if you switch off first chance exceptions for that specific exception. In Visual Studio, go to Debug-> Exceptions(or press Ctrl+ Alt+ E), Common Language Runtime Exceptions-> System.IO-> System.IO.FileNotFoundException.
如果您关闭该特定异常的第一次机会异常,则可以避免在调试时一直出现异常弹出窗口。在 Visual Studio 中,转到Debug-> Exceptions(或按Ctrl+ Alt+ E),Common Language Runtime Exceptions-> System.IO-> System.IO.FileNotFoundException。
You can find information about another way around it in the blog post C# XmlSerializer FileNotFound exception(which discusses Chris Sells' tool XmlSerializerPreCompiler).
您可以在博客文章C# XmlSerializer FileNotFound 异常(讨论 Chris Sells 的工具XmlSerializerPreCompiler)中找到有关另一种解决方法的信息。
回答by Zyphrax
Troubleshooting compilation errors on the other hand is very complicated. These problems manifest themselves in a FileNotFoundException with the message:
另一方面,排除编译错误非常复杂。这些问题在带有消息的 FileNotFoundException 中表现出来:
File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
at System.Reflection.Assembly.nLoad( ... )
at System.Reflection.Assembly.InternalLoad( ... )
at System.Reflection.Assembly.Load(...)
at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly()
You may wonder what a file not found exception has to do with instantiating a serializer object, but remember: the constructor writes C# files and tries to compile them. The call stack of this exception provides some good information to support that suspicion. The exception occurred while the XmlSerializer attempted to load an assembly generated by CodeDOM calling the System.Reflection.Assembly.Load method. The exception does not provide an explanation as to why the assembly that the XmlSerializer was supposed to create was not present. In general, the assembly is not present because the compilation failed, which may happen because, under rare circumstances, the serialization attributes produce code that the C# compiler fails to compile.
您可能想知道未找到文件异常与实例化序列化程序对象有什么关系,但请记住:构造函数编写 C# 文件并尝试编译它们。此异常的调用堆栈提供了一些很好的信息来支持这种怀疑。XmlSerializer 尝试加载由调用 System.Reflection.Assembly.Load 方法的 CodeDOM 生成的程序集时发生异常。该异常没有解释为什么 XmlSerializer 应该创建的程序集不存在。通常,程序集不存在是因为编译失败,这可能是因为在极少数情况下,序列化属性生成 C# 编译器无法编译的代码。
NoteThis error also occurs when the XmlSerializer runs under an account or a security environment that is not able to access the temp directory.
注意当 XmlSerializer 在无法访问临时目录的帐户或安全环境下运行时,也会发生此错误。
Source: http://msdn.microsoft.com/en-us/library/aa302290.aspx
回答by VladV
In Visual Studio project properties ("Build" page, if I recall it right) there is an option saying "generate serialization assembly". Try turning it on for a project that generates [Containing Assembly of MyType].
在 Visual Studio 项目属性(“Build”页面,如果我没记错的话)有一个选项说“生成序列化程序集”。尝试为生成[Containing Assembly of MyType]的项目打开它。
回答by Henrik
Your type may reference other assemblies which cannot be found neither in the GACnor in your local bin folder ==> ...
您的类型可能会引用在GAC或本地 bin 文件夹中都找不到的其他程序集==> ...
"or one of its dependencies. The system cannot find the file specified"
“或其依赖项之一。系统找不到指定的文件”
Can you give an example of the type you want to serialize?
你能举一个你想要序列化的类型的例子吗?
Note: Ensure that your type implements Serializable.
注意:确保您的类型实现了 Serializable。
回答by shahjapan
A custom class to serialise:
要序列化的自定义类:
[Serializable]
public class TestClass
{
int x = 2;
int y = 4;
public TestClass(){}
public TestClass(int x, int y)
{
this.x = x;
this.y = y;
}
public int TestFunction()
{
return x + y;
}
}
I have attached the code snippet. Maybe this can help you out.
我附上了代码片段。也许这可以帮助你。
static void Main(string[] args)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));
MemoryStream memoryStream = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
TestClass domain = new TestClass(10, 3);
xmlSerializer.Serialize(xmlWriter, domain);
memoryStream = (MemoryStream)xmlWriter.BaseStream;
string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());
TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);
Console.WriteLine(xmlDomain.TestFunction().ToString());
Console.ReadLine();
}
回答by Allon Guralnek
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.
正如 Martin Sherburn 所说,这是正常行为。XmlSerializer 的构造函数首先尝试查找名为 [YourAssembly].XmlSerializers.dll 的程序集,该程序集应包含生成的用于序列化类型的类。由于尚未生成这样的 DLL(默认情况下它们不是),因此抛出 FileNotFoundException。发生这种情况时,XmlSerializer 的构造函数会捕获该异常,并且 XmlSerializer 的构造函数会在运行时自动生成 DLL(这是通过在计算机的 %temp% 目录中生成 C# 源文件,然后使用 C# 编译器编译它们来完成的)。相同类型的 XmlSerializer 的其他构造将仅使用已生成的 DLL。
UPDATE:Starting from .NET 4.5,
XmlSerializer
no longer performs code generation nor does it perform compilation with the C# compiler in order to create a serializer assembly at runtime, unless explicitly forced to by setting a configuration file setting (useLegacySerializerGeneration). This change removes the dependency oncsc.exe
and improves startup performance. Source: .NET Framework 4.5 Readme, section 1.3.8.1.
更新:从 .NET 4.5 开始,
XmlSerializer
不再执行代码生成,也不再使用 C# 编译器执行编译以在运行时创建序列化程序集,除非通过设置配置文件设置(useLegacySerializerGeneration)明确强制执行。此更改消除了对csc.exe
启动性能的依赖并提高了启动性能。来源:.NET Framework 4.5 自述文件,第 1.3.8.1 节。
The exception is handled by XmlSerializer's constructor. There is no need to do anything yourself, you can just click 'Continue' (F5) to continue executing your program and everything will be fine. If you're bothered by the exceptions stopping the execution of your program and popping up an exception helper, you either have 'Just My Code' turned off, or you have the FileNotFoundException set to break execution when thrown, instead of when 'User-unhandled'.
该异常由 XmlSerializer 的构造函数处理。无需自己做任何事情,您只需单击“继续”(F5)即可继续执行您的程序,一切都会好起来的。如果您对停止执行程序并弹出异常帮助程序的异常感到困扰,您可以关闭“仅我的代码”,或者将 FileNotFoundException 设置为在抛出时中断执行,而不是在“用户”未处理'。
To enable 'Just My Code', go to Tools >> Options >> Debugging >> General >> Enable Just My Code. To turn off breaking of execution when FileNotFound is thrown, go to Debug >> Exceptions >> Find >> enter 'FileNotFoundException' >> untick the 'Thrown' checkbox from System.IO.FileNotFoundException.
要启用“仅我的代码”,请转到工具>>选项>>调试>>常规>>启用仅我的代码。要在抛出 FileNotFound 时关闭执行中断,请转到调试 >> 异常 >> 查找 >> 输入 'FileNotFoundException' >> 取消选中 System.IO.FileNotFoundException 中的 'Thrown' 复选框。
回答by HiredMind
This exception can also be trapped by a managed debugging assistant(MDA) called BindingFailure.
此异常也可以被称为 BindingFailure的托管调试助手(MDA)捕获。
This MDA is useful if your application is designed to ship with pre-build serialization assemblies. We do this to increase performance for our application. It allows us to make sure that the pre-built serialization assemblies are being properly built by our build process, and loaded by the application without being re-built on the fly.
如果您的应用程序设计为带有预构建序列化程序集,则此 MDA 非常有用。我们这样做是为了提高应用程序的性能。它使我们能够确保我们的构建过程正确构建了预构建的序列化程序集,并由应用程序加载,而无需即时重新构建。
It's really not useful except in this scenario, because as other posters have said, when a binding error is trapped by the Serializer constructor, the serialization assembly is re-built at runtime. So you can usually turn it off.
除了在这种情况下,它真的没有用,因为正如其他海报所说,当 Serializer 构造函数捕获绑定错误时,序列化程序集会在运行时重新构建。所以你通常可以关闭它。
回答by Ami Bar
To avoid the exception you need to do two things:
为了避免异常,您需要做两件事:
- Add an attribute to the serialized class (I hope you have access)
- Generate the serialization file with sgen.exe
- 给序列化的类添加一个属性(希望你有权限)
- 使用 sgen.exe 生成序列化文件
Add the System.Xml.Serialization.XmlSerializerAssembly attribute to your class. Replace 'MyAssembly' with the name of the assembly where MyClass is in.
将 System.Xml.Serialization.XmlSerializerAssembly 属性添加到您的类。将“MyAssembly”替换为 MyClass 所在的程序集的名称。
[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{
…
}
Generate the serialization file using the sgen.exe utility and deploy it with the class's assembly.
使用 sgen.exe 实用程序生成序列化文件并将其与类的程序集一起部署。
‘sgen.exe MyAssembly.dll' will generate the file MyAssembly.XmlSerializers.dll
'sgen.exe MyAssembly.dll' 将生成文件 MyAssembly.XmlSerializers.dll
These two changes will cause the .net to directly find the assembly. I checked it and it works on .NET framework 3.5 with Visual Studio 2008
这两个更改会导致.net 直接找到程序集。我检查了它,它在 .NET framework 3.5 和 Visual Studio 2008 上工作
回答by Pascal
In Visual Studio project properties there is an option saying "generate serialization assembly". Try turning it on for a project that generates [Containing Assembly of MyType].
在 Visual Studio 项目属性中有一个选项说“生成序列化程序集”。尝试为生成 [Containing Assembly of MyType] 的项目打开它。
回答by kay.one
I was getting the same error, and it was due to the type I was trying to deserialize not having a default parameterless constructor. I added a constructor, and it started working.
我遇到了同样的错误,这是由于我试图反序列化的类型没有默认的无参数构造函数。我添加了一个构造函数,它开始工作了。