我XmlSerializer
用来序列化然后反序列化一个简单的对象。当我惊讶地反序列化对象时,我发现一个子对象没有正确反序列化,而是变成了XmlNode[]
.
这几乎是我得到的结构:
// This line I put in here as a way of sneaking into the XML the
// root node's C# namespace, since it's not the same as the
// deserializing code and the deserializing code seemed unable to
// deserialize properly without knowing the Type (see my code below).
// So I basically just use this fake construct to get the namespace
// and make a Type of it to feed the XmlSerializer() instantiation.
[XmlRoot(Namespace = "http://foo.com/CSharpNamespace/Foo.Bar")]
// This is because QueuedFile can be given to the Argument array.
[XmlInclude(typeof(QueuedFile))]
// This class is Foo.Bar.CommandAndArguments
public class CommandAndArguments {
public String Command;
public object[] Arguments;
}
// I don't think this matters to XmlSerialize, but just in case...
[Serializable()]
// I added this line just thinking maybe it would help, but it doesn't
// do anything. I tried it without the XmlType first, and that
// didn't work.
[XmlType("Foo.Baz.Bat.QueuedFile")]
// This class is Foo.Baz.Bat.QueuedFile (in a different c#
// namespace than CommandAndArguments and the deserializing code)
public QueuedFile {
public String FileName;
public String DirectoryName;
}
反序列化它的代码如下所示:
public static object DeserializeXml(String objectToDeserialize)
{
String rootNodeName = "";
String rootNodeNamespace = "";
using (XmlReader xmlReader = XmlReader.Create(new StringReader(objectToDeserialize)))
{
if (xmlReader.MoveToContent() == XmlNodeType.Element)
{
rootNodeName = xmlReader.Name;
rootNodeNamespace = xmlReader.NamespaceURI;
if (rootNodeNamespace.StartsWith("http://foo.com/CSharpNamespace/"))
{
rootNodeName = rootNodeNamespace.Substring("http://foo.com/CSharpNamespace/".Length) + "." +
rootNodeName;
}
}
}
//MessageBox.Show(rootNodeName);
try
{
Type t = DetermineTypeFromName(rootNodeName);
if (t == null)
{
throw new Exception("Could not determine type of serialized string. Type listed as: "+rootNodeName);
}
var s = new XmlSerializer(t);
return s.Deserialize(new StringReader(objectToDeserialize));
// object o = new object();
// MethodInfo castMethod = o.GetType().GetMethod("Cast").MakeGenericMethod(t);
// return castMethod.Invoke(null, new object[] { s.Deserialize(new StringReader(objectToDeserialize)) });
}
catch (InvalidOperationException)
{
return null;
}
}
这CommandAndArguments
是序列化时的 XML:
<?xml version="1.0" encoding="utf-16"?>
<CommandAndArguments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://foo.com/CSharpNamespace/Foo.Bar">
<Command>I am a command</Command>
<Arguments>
<anyType xsi:type="Foo.Baz.Bat.QueuedFile">
<FileName xmlns="">HelloWorld.txt</FileName>
<DirectoryName xmlns="">C:\foo\bar</DirectoryName>
</anyType>
</Arguments>
</CommandAndArguments>
但是当我反序列化时,我得到一个CommandAndArguments
对象,其中 Arguments 是XmlNode[]
第一项是属性,将 QueuedFile 作为类型,其他索引是属性的元素。但是为什么没有QueuedFile
重新创建对象?
我怀疑这可能与 C# 命名空间有关,并且进行反序列化的引擎无法找到或使用QueuedFile
...现在我已经添加了我没有错误,只是一个不完整的反序列化。XmlInclude()
QueuedFile
XmlInclude()
帮助?我已经阅读了我能找到的所有内容,并在谷歌上搜索了我所知道的所有内容并被卡住了。我当然有很多关于 XML 序列化的知识要学习,但我不确定我是如何在应该很简单的事情上失败的(实际上我之前做过几乎完全一样的事情,没有任何问题,唯一的区别是一切都是在同一个 C# 命名空间中)。