我必须使用以下代码进行序列化:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace MyExample
{
class Program
{
static void Main(string[] args)
{
MyXmlDocument document = new MyXmlDocument();
document.MyExample.NodeA.value = "Value To Node A";
document.MyExample.NodeB.value = "Value To Node B";
document.MyExample.NodeC.value = 1234.567;
document.WriteToXml(@"C:\Users\E9JR\Desktop\mydocument.xml");
Console.Write("> Done!");
Console.ReadKey();
}
}
[XmlRoot(ElementName="xmlExample",IsNullable=false)]
public class XmlExample
{
private NodeA_Elem _nodea;
[XmlElement()]
public NodeA_Elem NodeA
{
get
{
return _nodea;
}
set
{
_nodea = value;
}
}
public bool ShouldSerializeNodeA()
{
return !String.IsNullOrEmpty(_nodea.value);
}
private NodeB_Elem _nodeb;
[XmlElement(ElementName = "NodeB", IsNullable = false)]
public NodeB_Elem NodeB
{
get
{
return _nodeb;
}
set
{
_nodeb = value;
}
}
public bool ShouldSerializeNodeB()
{
return !String.IsNullOrEmpty(_nodeb.value);
}
private NodeC_Elem _nodec;
[XmlElement(ElementName = "NodeC",IsNullable=false)]
public NodeC_Elem NodeC
{
get
{
return _nodec;
}
set
{
_nodec = value;
}
}
public bool ShouldSerializeNodeC()
{
return _nodec.value.HasValue;
}
public XmlExample()
{
_nodea = new NodeA_Elem();
_nodeb = new NodeB_Elem();
_nodec = new NodeC_Elem();
}
}
public class NodeA_Elem
{
[XmlText()]
public string value { get; set; }
}
public class NodeB_Elem
{
[XmlText()]
public string value { get; set; }
}
public class NodeC_Elem
{
[XmlText()]
public double? value { get; set; }
}
public class MyXmlDocument
{
private XmlExample _myexample;
public XmlExample MyExample
{
get
{
return _myexample;
}
set
{
_myexample = value;
}
}
public void WriteToXml(string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlExample));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = Encoding.Unicode;
StringWriter txtwriter = new StringWriter();
XmlWriter xmlwtr = XmlWriter.Create(txtwriter, settings);
serializer.Serialize(xmlwtr, MyExample);
StreamWriter writer = new StreamWriter(path);
writer.Write(txtwriter.ToString());
writer.Close();
}
public void ReadXml(string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlExample));
StreamReader reader = new StreamReader(path);
MyExample = (XmlExample)serializer.Deserialize(reader);
}
public MyXmlDocument()
{
_myexample = new XmlExample();
}
}
}
我正在尝试使用value属性作为节点的文本序列化NodeC,这是一个double,但它不起作用,即使使用ShouldSerialize模式来避免序列化空节点。 NodeA和NodeB工作正常。我需要NodeC的帮助。
答案 0 :(得分:3)
您无法将可为空的双重序列化为XmlText
。如果你看一下你所获得的System.InvalidOperationException
的全文,你会看到类似的内容:
InnerException: System.InvalidOperationException
Message="Cannot serialize member 'value' of type System.Nullable`1[System.Double]. XmlAttribute/XmlText cannot be used to encode complex types."
Source="System.Xml"
StackTrace:
at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
该消息是自我解释的。来自documentation for XmlTextAttribute
:
您可以将XmlTextAttribute应用于返回基元和枚举类型的公共字段和公共读/写属性。
您可以将XmlTextAttribute应用于返回字符串数组的字段或属性。您还可以将该属性应用于Object类型的数组,但必须将Type属性设置为string。在这种情况下,插入到数组中的任何字符串都被序列化为XML文本。
XmlTextAttribute也可以应用于返回XmlNode或XmlNode对象数组的字段。
要理解为什么ShouldSerializeXXX()
在这里没有帮助,您应该了解XmlSerializer
works as follows:
第一次序列化类型时,XmlSerializer
构造函数在内部编写运行时c#代码,以使用反射对类型和所有引用类型的实例进行序列化和反序列化,然后编译代码并加载将DLL导入内存。
随后,类实例的序列化和反序列化由先前创建的动态DLL执行。
但是第1步无法访问该类的实例。它基于类型信息创建其动态库。而且,根据类型信息,当ShouldSerializeXXX()
为空时,无法推断相关的false
方法将返回double? value
。因此,动态代码生成中止,因为无法生成将可空双精度写为XmlText的代码。
作为一种解决方法,您可以创建一个表示double的字符串属性:
public class NodeC_Elem
{
[XmlIgnore]
public double? value { get; set; }
[XmlText]
public string StringValue
{
get
{
if (value == null)
return null;
return XmlConvert.ToString(value.Value);
}
set
{
if (value == null)
{
this.value = null;
return;
}
this.value = XmlConvert.ToDouble(value);
}
}
}