2012-07-24 14 views
7

zaimplementować IXmlSerializable dla danego typu, poniżej której koduje wartość koloru RGB jako jeden ciąg znaków:Jak używać niestandardowego IXmlSerializable jako 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); 
    } 
} 

Ponieważ jest to pojedynczy łańcuch, chciałam zapisać go jako atrybut celu zaoszczędzenia miejsca. Ale jak tylko dodać [XmlAttribute] do mojego mienia, pojawia się następujący wyjątek: { „. Nie można szeregować członkowskiego«kolor»typu SerializableColor XmlAttribute/xmlText nie może być używany do kodowania rodzajów wykonawczych IXmlSerializable”}

Czy istnieje sposób, aby działało to również jako atrybut?

Odpowiedz

4

Błąd oznacza dokładnie to, co mówi. Nie można korzystać z tych atrybutów serializacji XML po zaimplementowaniu IXmlSerializable, ponieważ program IXmlSerializable oczekuje, że serializacja XML będzie całkowicie dostosowana. Możesz to zrobić, jeśli chcesz uczynić klasę serializowalną za pomocą XmlSerializer za pomocą atrybutów.

[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; }  
} 

Ponadto, dla realizacji 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); 
    } 

Jeśli, z drugiej strony, wszystko, czego szukasz w stanie zrobić, to mieć krótki represenation ciąg kolor, który jest odwracalny , spójrz na ColorTranslator Class. W szczególności zobacz metody FromHtml i ToHtml.

+0

Dziękuję za odpowiedź. Mam jednak dwa pytania. Po pierwsze, w jaki sposób implementacja nie jest poprawna? Wygląda trochę jak przykład podany [w dokumentacji] (http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx) (z adendum opisanym w sekcji komentarza). Po drugie, czy atrybut XmlRoot jest odpowiedni w tym przykładzie? Jakie to różnice? –

+0

Jeśli chodzi o implementację, która nie zapewnia poprawnego XML, zapomniałem, że "framework zapisuje element opakowania i ustawia pisarza XML po jego uruchomieniu". Poprawię odpowiedź. Możesz faktycznie opuścić XmlRoot, jak można wywnioskować przez XmlSerializer, jednak, gdy nadpisuję domyślne zachowanie serializacji na klasie, zwykle robię to na wszystkich składnikach dla jasności. – JamieSee

+0

Wcześniej przegłosowałem, ponieważ OP pyta, kogo utworzyć dostosowalny atrybut XML. NIE tworząc elementu XML. –

6

Niestety (& dziwnie) nie jest możliwe zgodnie z tym linkiem http://connect.microsoft.com/VisualStudio/feedback/details/277641/xmlattribute-xmltext-cannot-be-used-to-encode-types-implementing-ixmlserializable

Aby obejść problem, Obecnie używam atrybut XmlIgnore ukryć złożoną nieruchomości i wystawiać go jako ciąg poprzez inną nieruchomość

public class MyDto 
{ 
    [XmlAttribute(AttributeName = "complex-attribute")] 
    public string MyComplexPropertyAsString 
    { 
     get { return MyComplexMember.ToString(); } 
     set { MyComplexMember.LoadFromString(value); } 
    } 
    [XmlIgnore] 
    public MyComplexMember At { get; set; } 
} 
Powiązane problemy