如何在c#中通过XML序列化输出十六进制数?

如何在c#中通过XML序列化输出十六进制数?,c#,hex,xmlserializer,C#,Hex,Xmlserializer,我有一些类和结构,我使用XML序列化来保存和调用数据,但我想要的一个特性是以十六进制表示输出整数。有什么属性可以挂在这些结构上实现这一点吗?您可以实现完全自定义的序列化,但这可能有点过分。如何公开一个属性MyIntegerAsHex,该属性以字符串形式返回整数,格式为十六进制数:MyInteger.ToString(“X”)属性将需要一个setter,即使它是一个计算字段,以便序列化对象中的字符串可以在反序列化时馈送到新实例中 然后,您可以实现一个反序列化回调,或者只将代码放入setter,当对

我有一些类和结构,我使用XML序列化来保存和调用数据,但我想要的一个特性是以十六进制表示输出整数。有什么属性可以挂在这些结构上实现这一点吗?

您可以实现完全自定义的序列化,但这可能有点过分。如何公开一个属性
MyIntegerAsHex
,该属性以字符串形式返回整数,格式为十六进制数:
MyInteger.ToString(“X”)
属性将需要一个setter,即使它是一个计算字段,以便序列化对象中的字符串可以在反序列化时馈送到新实例中

然后,您可以实现一个反序列化回调,或者只将代码放入setter,当对象被反序列化时,该回调将把十六进制数解析为十进制整数:
MyInteger=int.parse(IntegerAsHex,NumberStyles.allowehxnumber)

总而言之,您的房产看起来是这样的:

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

然后,如果您不想在XML文件中将数字视为十进制整数,只需使用[XmlIgnore]标记即可。

有一点代码味道,但以下将起作用:

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>

f6fd21a

我从KeithS和code4life中提出了一个稍微改进的变通方法

这样做的好处是xsd.exe工具将把type属性设置为
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>

我知道,最后一个答案是两年多前,但我正在寻找一个解决方案,并找到了这个线索。但对提议的解决方案不满意,因此我尝试找到自己的解决方案:

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>

0x006452B0
您可以调整解决方案以获得所需的确切格式,并完成HInt32结构,使其更“Int32 complient”。
警告:此解决方案不能用于将属性序列化为属性。

我使用了此方法。虽然这是一个有点气味,它是简单的阅读效果很好。
<?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>