如何使用自定义IXmlSerializable作为XmlAttribute?
问题描述:
我实现IXmlSerializable
低于其编码RGB颜色值作为一个字符串类型:如何使用自定义IXmlSerializable作为XmlAttribute?
public class SerializableColor : IXmlSerializable
{
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var data = reader.ReadString();
reader.ReadEndElement();
var split = data.Split(' ');
R = int.Parse(split[0]);
G = int.Parse(split[1]);
B = int.Parse(split[2]);
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(R + " " + G + " " + B);
}
}
因为它是一个字符串,我想把它保存为一个属性,以节省空间。但只要我添加[XmlAttribute]
我的财产,我得到以下异常:{“无法序列成员类型SerializableColor的‘颜色’XmlAttribute/XMLTEXT不能用来编码类型执行IXmlSerializable的”}
有没有办法让它作为一个属性工作?
答
错误的含义正是它所说的。当实现IXmlSerializable时,您不能使用这些XML序列化属性,因为IXmlSerializable期望XML序列化完全自定义。如果要使用属性使XmlSerializer可序列化,则可以执行此操作。
[XmlRoot("SerializableColor")]
public class SerializableColor
{
[XmlAttribute("R")]
public int R { get; set; }
[XmlAttribute("G")]
public int R { get; set; }
[XmlAttribute("B")]
public int B { get; set; }
}
此外,为您实现XmlSerializable的:
public void ReadXml(XmlReader reader)
{
string data = null;
reader.MoveToAttribute("Color");
if (reader.ReadAttributeValue())
{
data = reader.Value;
}
reader.ReadEndElement();
var split = data.Split(' ');
R = int.Parse(split[0]);
G = int.Parse(split[1]);
B = int.Parse(split[2]);
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("Color", R + " " + G + " " + B);
}
如果,另一方面,你正在寻找能够做的是有一个颜色,是可逆的短字符串represenation ,看看ColorTranslator Class。具体来说,请参阅FromHtml和ToHtml方法。
答
可悲的是(&奇怪),它根据这个链接http://connect.microsoft.com/VisualStudio/feedback/details/277641/xmlattribute-xmltext-cannot-be-used-to-encode-types-implementing-ixmlserializable
是不可能变通的问题,我目前使用的XmlIgnore属性隐藏复杂属性并将其作为通过其他属性的字符串
public class MyDto
{
[XmlAttribute(AttributeName = "complex-attribute")]
public string MyComplexPropertyAsString
{
get { return MyComplexMember.ToString(); }
set { MyComplexMember.LoadFromString(value); }
}
[XmlIgnore]
public MyComplexMember At { get; set; }
}
谢谢你的回答。但我有两个问题。首先,实施过程如何不正确?看起来非常像[在文档中]给出的示例(http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.ixmlserializable.aspx)(在注释部分中描述了附录)。第二,这个例子中的XmlRoot属性是相关的吗?它有什么不同? – 2012-07-24 19:33:49
关于不生成正确XML的实现,我忘记了“框架写入一个包装器元素并在启动后定位XML编写器”。我会修改答案。实际上,XmlRoot可以由XmlSerializer推断出来,但是,当我重写某个类的默认序列化行为时,为了清楚起见,我通常在它的所有组件上执行此操作。 – JamieSee 2012-07-24 20:24:13
因为OP询问谁来创建可自定义的XML属性,所以我投了票。不产生一个XML元素。 – 2012-10-03 08:44:37