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

发布于 2024-09-25 17:17:03 字数 83 浏览 3 评论 0原文

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

I've got a few classes and structures that I use XML serialization to save and recall data, but a feature that I'd like to have is to output integers in hex representation. Is there any attribute that I can hang on these structure to make that happen?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤独患者 2024-10-02 17:17:03

有一点代码味道,但以下工作:

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>

There's a bit of code smell, but the following will work:

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 the class in a console program:

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

The result:

<?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>
一梦浮鱼 2024-10-02 17:17:03

我知道,最后一个答案是两年多前,但我一直在寻找解决方案并找到了这个帖子。但对提出的解决方案不满意,所以我尝试找到自己的解决方案:

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”。
警告:此解决方案不能用于将属性序列化为属性。

I know, last answer was more than two years ago, but I was looking for have a solution and found this thread. But wasn't satisfied by proposed solutions so I tried to find my own 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); }
}

Now you can use this type instead of Int32 in your serialized class :

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

The result is :

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

You can adapt the solution to get the exact format you want and complete the HInt32 struct to be more "Int32 complient".
Warning : This solution can't be use to serialize a property as an attribute.

旧话新听 2024-10-02 17:17:03

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

然后,您可以实现反序列化回调,或者只是将代码放入 setter 中,以便在反序列化对象时将十六进制数字解析为十进制整数:MyInteger = int.Parse(IntegerAsHex, NumberStyles.AllowHexNumber);

因此,总而言之,您的属性将如下所示:

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

然后,如果您不想在 XML 文件中看到该数字作为十进制整数,只需用 [XmlIgnore] 对其进行标记即可。

You can implement fully custom serialization, but that's probably a bit much for this. How about exposing a property MyIntegerAsHex, that returns the integer as a string, formatted as a hexadecimal number: MyInteger.ToString("X"); The property will need a setter, even though it's a calculated field, so that the string from the serialized object can be fed into a new instance on deserialization.

You can then implement a deserialization callback, or just put code in the setter, that will parse the hex number to a decimal integer when the object is deserialized: MyInteger = int.Parse(IntegerAsHex, NumberStyles.AllowHexNumber);

So, in summary, your property would look something like this:

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

Then, if you didn't want to see the number as a decimal integer in the XML file, just tag it with [XmlIgnore].

誰認得朕 2024-10-02 17:17:03

我从 KeithScode4life 中提出了一个稍微改进的解决方法。

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 工具会将 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>

I came up with a slightly improved variant of the workaround from KeithS and 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);
        }
    }
}

The benefit of this is that the xsd.exe tool will set the type attribute to xs:hexBinary instead of 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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文