2012-07-24 6 views
7

私は1つの文字列としてRGBカラー値を符号化し、それ以下のタイプのためにIXmlSerializableを実装:カスタム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は、IXmlSerializableがXMLシリアル化が完全にカスタマイズされることを期待しているため、これらの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

ありがとうございました。私は2つの質問がある。まず、実装はどのように正しくないのですか?ドキュメントの中の例(http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx)によく似ています(コメント欄に説明があります)。もう1つは、この例ではXmlRoot属性ですか?それはどのような違いがありますか? –

+0

正しいXMLを生成できない実装に関して、私は忘れていました。「フレームワークはラッパー要素を記述し、XMLライターを起動後に配置します。」私は答えを改めるつもりです。実際には、XmlSerializerによって推論できるようにXmlRootをそのまま残すことができますが、クラスのデフォルトのシリアル化動作をオーバーライドするときは、わかりやすくするために、通常はすべてのコンポーネントで行います。 – JamieSee

+0

OPはカスタマイズ可能なXML属性を誰に作成するかを尋ねているので、私はダウン投票しました。 XML要素を生成しません。 –

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; } 
} 
関連する問題