【发布时间】:2025-12-29 13:45:11
【问题描述】:
考虑一个简单的案例
public class Test {
public String myString;
}
有什么方法可以告诉 XmlSerializer 在序列化时对 myString 进行 base64 编码?
【问题讨论】:
标签: c# xml-serialization
考虑一个简单的案例
public class Test {
public String myString;
}
有什么方法可以告诉 XmlSerializer 在序列化时对 myString 进行 base64 编码?
【问题讨论】:
标签: c# xml-serialization
您可以简单地将其设置为 byte[] 属性,它会自动对其进行 Base64 编码:
public class Test {
public byte[] MyProperty {get;set;}
public void SetMyProperty(string text)
{
MyProperty = System.Text.Encoding.Unicode.GetBytes(text);
}
}
Test test = new Test();
test. SetMyProperty("123456789123456789");
输出:
<MyProperty>MQAyADMANAA1ADYANwA4ADkAMQAyADMANAA1ADYANwA4ADkA</MyProperty>
(尝试解码here)
不幸的是,没有办法(据我所知)将 MyProperty 设为私有并且仍然在 System.Xml.Serialization 中序列化。
【讨论】:
Base64 将 二进制 数据转换为字符串。如果要对字符串中的数据进行 base64 编码,则需要先将其编码为字节数组,例如使用Encoding.UTF.GetBytes(myString)。
这引发了一个问题,即为什么您首先要这样做。如果你需要使用 base 64,你确定你真的有文本数据开始吗?
【讨论】:
" " 和 "\0" 在默认情况下在往返 XML 的往返行程中存活会很好。
按照 Jon Grant 的有用建议,我实现了一个 Base64String 类型,它封装了所需的 Base64 编码。
public class Base64String: IXmlSerializable
{
private string value;
public Base64String() { }
public Base64String(string value)
{
this.value = value;
}
public string Value
{
get { return value; }
set { this.value = value; }
}
public static implicit operator string(Base64String x)
{
return x.ToString();
}
public static implicit operator Base64String(string x)
{
return new Base64String(x);
}
public override string ToString()
{
return value;
}
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
MemoryStream ms = null;
byte[] buffer = new byte[256];
int bytesRead;
while ((bytesRead = reader.ReadElementContentAsBase64(buffer, 0, buffer.Length)) > 0)
{
if (ms == null)
ms = new MemoryStream(bytesRead);
ms.Write(buffer, 0, bytesRead);
}
if (ms != null)
value = System.Text.UnicodeEncoding.Unicode.GetString(ms.ToArray());
}
public void WriteXml(System.Xml.XmlWriter writer)
{
if (!string.IsNullOrEmpty(value))
{
byte[] rawData = Encoding.Unicode.GetBytes(value);
writer.WriteBase64(rawData, 0, rawData.Length);
}
}
static public string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.UnicodeEncoding.Unicode.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
static public string DecodeFrom64(string encodedData)
{
byte[] encodedDataAsBytes
= System.Convert.FromBase64String(encodedData);
string returnValue =
System.Text.UnicodeEncoding.Unicode.GetString(encodedDataAsBytes);
return returnValue;
}
#endregion
}
你可以像这样使用类型:
static void Main(string[] args)
{
Foo foo = new Foo();
foo.Field1 = "Pluto";
foo.Field2 = "Pippo";
foo.Field3 = "Topolino";
foo.Field4 = "Paperino";
XmlSerializer ser = new XmlSerializer(typeof(Foo));
ser.Serialize(Console.Out, foo);
Console.ReadLine();
}
[XmlRoot("Sample")]
public class Foo
{
public Foo() { }
[XmlElement("Alfa_64")]
public Base64String Field1;
[XmlElement("Beta")]
public string Field2;
[XmlElement("Gamma_64")]
public Base64String Field3;
[XmlElement("Delta_64")]
public Base64String Field4;
}
【讨论】:
您将字符串存储为 Base64 值,然后在 get 子句中拥有一个对其进行解码的属性。
【讨论】:
更改XmlSerializer 类的输出的唯一受支持方法(没有丑陋的技巧,例如具有特殊隐藏属性等)是实现IXmlSerializable 接口。
您可以通过定义一个实现IXmlSerializable 的Base64String 类并只写出编码字符串来省去为整个类编写序列化代码的麻烦。定义一个操作符,使其 implicitly castable 成为一个字符串,它的工作方式应该和普通字符串一样。
【讨论】: