【发布时间】:2022-11-20 07:18:42
【问题描述】:
我试图将一个 xml 字符串反序列化为一个对象,这没什么奇怪的。在我将我的项目升级到 .Net5 之前,一切都很好。
在升级中,我必须添加对包 Microsoft.XmlSerializer.Generator 的引用,并更改项目文件以添加以下内容:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="1.0.0" />
</ItemGroup>
这使我能够创建 XmlSerializer(第一个错误很奇怪)。但是,现在,如果该类具有 XmlRoot 属性,则每次对 XmlReader 上的 CanDeserialize 调用都会返回 false。现在,我可以反序列化 xml 文本。那确实有效。但是为什么 CanDeserialize 会基于这种情况而失败呢?
下面是我用来在控制台应用程序 (.Net5) 中测试的类和代码。
[Serializable, XmlRoot("TestObj")]
//[Serializable]
public class TestObj
{
public int TestVal;
}
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(TestObj));
//generated by doing a test serialization of the class
var teststr = "<TestObj xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><TestVal>2</TestVal></TestObj>";
using (var str = new StringReader(teststr))
using (var reader = XmlReader.Create(str))
{
if (serializer.CanDeserialize(reader))
Console.WriteLine(((TestObj)serializer.Deserialize(reader)).TestVal);
else
{
Console.WriteLine("Value cannot be deserialized into the given Type");
//try it anyway
var o = (TestObj)serializer.Deserialize(reader);
Console.WriteLine(o.TestVal);
}
}
}
我的解决方法只是消除 CanDeserialize 调用并将反序列化包装在 try..catch 中,但我仍然很好奇为什么会这样。
【问题讨论】:
-
嗯,无法使用 .NET 6 小提琴重现,请参阅dotnetfiddle.net/DwbPuZ。为什么需要添加对Microsoft.XmlSerializer.Generator 的引用?您实际上是否在构建时使用它为您的类型创建 XML 序列化程序集?
-
另外,如果你在调用
CanDeserialize之前调用XmlReader.MoveToContent()会发生什么? -
我必须测试 MoveToContent() 调用。我以前从来没有这样做过。由于我提到的奇怪错误,我不得不添加参考。创建 XmlSerializer 会失败。错误消息说找不到 {MyProject}.XmlSerializer.dll。是的,它认为 XmlSerializer 在我的项目命名空间中。哪怕我特地声明过。没有构建错误。我清理并重新启动了一切。 Generator 包是我能找到的唯一修复程序。
-
关于奇怪的错误,
new XmlSerializer()构造函数实际上失败?它在内部尝试在磁盘上查找已保存的序列化 DLL。如果不存在,则存在内部异常,但它会在构造函数中被捕获并吞噬,因此是无害的。参见XmlSerializer giving FileNotFoundException at constructor。您是否有机会在调试器或日志文件中看到第一次异常并认为这是问题所在,但实际问题完全不同? -
是的,新的构造函数失败了。该错误具体是在 XmlSerializer 上引用项目的命名空间。但是,您对此的质疑确实给了我一个尝试的想法,我现在将其作为答案发布。
标签: xml-serialization .net-5 xmlserializer