XMLシリアル化を使用してデータを保存および呼び出すクラスと構造がいくつかありますが、必要な機能は整数を16進表現で出力することです。それを実現するためにこれらの構造に掛けることができる属性はありますか?
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>
最後の回答は2年以上前でしたが、解決策を探していて、このスレッドを見つけました。しかし、提案された解決策に満足できなかったので、私は自分自身の解決策を見つけようとしました:
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 準拠」にすることができます。警告 : このソリューションを使用して、プロパティを属性としてシリアル化することはできません。
完全にカスタムのシリアライゼーションを実装することはできますが、これはおそらく少しやり過ぎです。MyIntegerAsHex
16 進数として書式設定された文字列として整数を返すプロパティを公開するのはどうですかMyInteger.ToString("X");
。シリアル化されたオブジェクトからの文字列を新しいインスタンスにフィードできるように、計算フィールドであっても、プロパティにはセッターが必要です。逆シリアル化。
次に、逆シリアル化コールバックを実装するか、オブジェクトが逆シリアル化されるときに 16 進数を 10 進数に解析するコードをセッターに入れることができます。MyInteger = int.Parse(IntegerAsHex, NumberStyles.AllowHexNumber);
つまり、要約すると、プロパティは次のようになります。
public string MyIntegerAsHex
{
get { return MyInteger.ToString("X"); }
set { MyInteger = int.Parse(value, NumberStyles.AllowHexNumber); }
}
次に、XML ファイルで数値を 10 進整数として表示したくない場合は、[XmlIgnore] でタグ付けします。
KeithSと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);
}
}
}
これの利点は、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>