2010-10-01 6 views

Répondre

1

Vous pouvez implémenter une sérialisation entièrement personnalisée, mais c'est probablement un peu trop pour cela. Que diriez-vous d'exposer une propriété MyIntegerAsHex, qui renvoie l'entier sous la forme d'une chaîne, formatée comme un nombre hexadécimal: MyInteger.ToString("X"); La propriété aura besoin d'un setter, même si c'est un champ calculé, de sorte que la chaîne de l'objet sérialisé peut être introduite dans un nouveau exemple sur la désérialisation.

Vous pouvez ensuite mettre en œuvre un rappel désérialisation ou le code vient de mettre dans le setter, qui analysera le nombre hexadécimal à un entier décimal lorsque l'objet est désérialisé: MyInteger = int.Parse(IntegerAsHex, NumberStyles.AllowHexNumber);

Donc, en résumé, votre propriété regarderait quelque chose comme ceci:

public string MyIntegerAsHex 
{ 
    get { return MyInteger.ToString("X"); } 
    set { MyInteger = int.Parse(value, NumberStyles.AllowHexNumber); } 
} 

Ensuite, si vous ne voulez pas voir le nombre comme un entier décimal dans le fichier XML, étiquette juste avec [XmlIgnore].

4

Il y a un peu d'odeur de code, mais le suivant va travail:

public class ViewAsHex 
{ 
    [XmlIgnore] 
    public int Value { get; set; } 

    [XmlElement(ElementName="Value")] 
    public string HexValue 
    { 
     get 
     { 
      // convert int to hex representation 
      return Value.ToString("x"); 
     } 
     set 
     { 
      // convert hex representation back to int 
      Value = int.Parse(value, 
       System.Globalization.NumberStyles.HexNumber); 
     } 
    } 
} 

Test de la classe dans un programme de console:

public class Program 
{ 
    static void Main(string[] args) 
    { 
     var o = new ViewAsHex(); 
     o.Value = 258986522; 

     var xs = new XmlSerializer(typeof(ViewAsHex)); 

     var output = Console.OpenStandardOutput(); 
     xs.Serialize(output, o); 

     Console.WriteLine(); 
     Console.WriteLine("Press enter to exit."); 
     Console.ReadLine(); 
    } 
} 

Le résultat:

<?xml version="1.0"?> 
<ViewAsHex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Value>f6fd21a</Value> 
</ViewAsHex> 
+0

J'ai utilisé cette approche. Alors que c'est un peu une odeur C'est simple à lire fonctionne bien. – rolls

1

Je suis venu avec une variante légèrement améliorée de la solution de contournement de KeithS et code4life.

using System; 
using System.Linq; 

public class Data 
{ 
    [XmlIgnore()] 
    public uint Value { get; set; } 
    [XmlAttribute("Value", DataType = "hexBinary")] 
    public byte[] ValueBinary 
    { 
     get 
     { 
      return BitConverter.GetBytes(Value).Reverse().ToArray(); 
     } 
     set 
     { 
      Value = BitConverter.ToUInt32(value.Reverse().ToArray(), 0); 
     } 
    } 
} 

L'avantage est que l'outil xsd.exe définit l'attribut de type à xs:hexBinary au lieu de xs:string ...

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="Data" nillable="true" type="Data" /> 
    <xs:complexType name="Data"> 
    <xs:attribute name="Value" type="xs:hexBinary" /> 
    </xs:complexType> 
</xs:schema> 
1

Je sais, dernière réponse était il y a plus de deux ans, mais je cherchais une solution et trouvé ce fil. Mais n'a pas été satisfaite par les solutions proposées alors j'ai essayé de trouver ma propre solution:

public struct HInt32 : IXmlSerializable 
{ 
    private int _Value; 

    public HInt32(int v) { _Value = v; } 

    XmlSchema IXmlSerializable.GetSchema() { return null; } 

    void IXmlSerializable.ReadXml(XmlReader reader) { _Value = Int32.Parse(reader.ReadContentAsString().TrimStart('0', 'x'), NumberStyles.HexNumber); } 

    void IXmlSerializable.WriteXml(XmlWriter writer) { writer.WriteValue("0x" + _Value.ToString("X2").PadLeft(8, '0')); } 

    public static implicit operator int(HInt32 v) { return v._Value; } 

    public static implicit operator HInt32(int v) { return new HInt32(v); } 
} 

Maintenant, vous pouvez utiliser ce type au lieu de Int32 dans votre classe sérialisée:

public TestClass 
{ 
    public HInt32 HexaValue { get; set; } 
} 

public void SerializeClass() 
{ 
    TestClass t = new TestClass(); 
    t.HexaValue = 6574768; // Transparent int assigment 

    XmlSerializer xser = new XmlSerializer(typeof(TestClass)); 
    StringBuilder sb = new StringBuilder(); 
    using(StringWriter sw = new StringWriter(sb)) 
    { 
     xser.Serialize(sw, t); 
    } 
    Console.WriteLine(sb.ToString()); 
} 

Le résultat est:

<?xml version="1.0" encoding="utf-16"?> 
<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <HexaValue>0x006452B0</HexaValue> 
</TestClass> 

Vous pouvez adapter la solution pour obtenir le format exact souhaité et compléter la structure HInt32 pour qu'elle soit plus "conforme à Int32". Avertissement: Cette solution ne peut pas être utilisée pour sérialiser une propriété en tant qu'attribut.

Questions connexes