2010-10-01 1 views
4

У меня есть несколько классов и структур, в которых я использую сериализацию XML для сохранения и воспроизведения данных, но функция, которую я хотел бы иметь, состоит в выводе целых чисел в шестнадцатеричном представлении. Есть ли какой-либо атрибут, который я могу повесить на эту структуру, чтобы это произошло?Как выводить шестнадцатеричные числа через XML-сериализацию в C#?

ответ

1

Вы можете реализовать полностью пользовательскую сериализацию, но это, вероятно, немного для этого. Как об экспонировании свойства MyIntegerAsHex, которое возвращает целое число в виде строки, отформатированное как шестнадцатеричное число: MyInteger.ToString("X"); Для свойства потребуется сеттер, даже если это вычисленное поле, так что строка из сериализованного объекта может быть загружена в новую при десериализации.

Вы можете осуществить десериализации обратный вызов, или просто поместить код в инкубаторе, который будет анализировать шестнадцатеричное число в десятичное целое число, когда объект десериализации: MyInteger = int.Parse(IntegerAsHex, NumberStyles.AllowHexNumber);

Так, в целом, ваша собственность будет выглядеть что-то вроде этого:

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

Затем, если вы не хотите, чтобы увидеть число как десятичное целое число в файле XML, просто пометить его с [XmlIgnore].

4

Там есть немного кода запаха, но следующий будет работы:

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

Тест класс в консольной программе:

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(); 
    } 
} 

Результат:

<?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

Я использовал этот подход. Хотя это немного запах, прост в чтении хорошо работает. – rolls

1

Я придумал несколько улучшенный вариант обходного пути от KeithS и код4life.

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

Преимущество этого в том, что инструмент xsd.exe будет установлен атрибут типа для xs:hexBinary вместо 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

Я знаю, последний ответ был более двух лет назад, но я искал решение и нашел эту тему. Но не была удовлетворена предлагаемыми решениями, поэтому я пытался найти свое собственное решение:

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

Теперь вы можете использовать этот тип вместо Int32 в вашем сериализованном классе:

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()); 
} 

Результат:

<?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> 

Вы можете адаптировать решение, чтобы получить точный формат и завершить структуру HInt32, чтобы быть более «Int32 complient». Предупреждение. Это решение не может использоваться для сериализации свойства как атрибута.