2012-07-24 39 views
7

我实现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的”}

有没有办法让它作为一个属性工作?

回答

4

错误的含义正是它所说的。当实现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方法。

+0

谢谢你的回答。但我有两个问题。首先,实施过程如何不正确?看起来非常像[在文档中]给出的示例(http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.ixmlserializable.aspx)(在注释部分中描述了附录)。第二,这个例子中的XmlRoot属性是相关的吗?它有什么不同? – 2012-07-24 19:33:49

+0

关于不生成正确XML的实现,我忘记了“框架写入一个包装器元素并在启动后定位XML编写器”。我会修改答案。实际上,XmlRoot可以由XmlSerializer推断出来,但是,当我重写某个类的默认序列化行为时,为了清楚起见,我通常在它的所有组件上执行此操作。 – JamieSee 2012-07-24 20:24:13

+0

因为OP询问谁来创建可自定义的XML属性,所以我投了票。不产生一个XML元素。 – 2012-10-03 08:44:37

6

可悲的是(&奇怪),它根据这个链接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; } 
}