Jak*_*keL 5 c# xml serialization
在我们的应用程序中,我们有一个Money类型,其中包含一个金额(十进制)和一个货币代码(字符串)。简单来说,它看起来像这样:
public class Money
{
public decimal Amount{get;set;}
public string CurrencyCode{get;set;}
}
Run Code Online (Sandbox Code Playgroud)
就像您想象的那样,它在应用程序的许多地方都得到了使用,并且在发送到客户端或从客户端发送时经常被序列化/反序列化。货币金额通常序列化为复合值,例如“ 1.23USD”代表$ 1.23。旧客户端(HTML / JS)会将其值解析为其组成部分,再转换为Money类型。Money值作为元素值和属性值发送,具体取决于它们在应用程序中的位置,例如:
<SomeClass moneyValue="1.23USD" ... />
Run Code Online (Sandbox Code Playgroud)
要么
<SomeClass>
<MoneyValue>1.23USD</MoneyValue>
...
</SomeClass>
Run Code Online (Sandbox Code Playgroud)
我试图找出一种方法,可以使用内置的C#/。NET Xml序列化工具来具有相同的行为。我研究了实现ISerializable的方法,但是还没有找到完全正确的方法。
本质上,我希望能够通过自己的自定义逻辑对货币金额进行反序列化(知道如何将“ 1.23USD”解析为货币金额),并将其序列化为简单的字符串,例如“ 1.23USD”
最终目标将是使某个类中的货币金额如下:
[XmlAttribute]
public Money SomeField // SomeField='123.USD
Run Code Online (Sandbox Code Playgroud)
要么:
[XmlElement]
public Money SomeOtherField //<SomeOtherField>1.23USD</SomeOtherField>
Run Code Online (Sandbox Code Playgroud)
就像您可以使用简单类型(例如int,string,double等)一样进行操作。
这可能吗?
事实证明,这真的不是一个好的 100% 答案 - 问题是您无法将复杂类型(例如 Money)序列化为属性,即使将其序列化为简单字符串也是如此。所以无论如何,我不能有 someAttribute='1.23 USD' 可以以一般方式重复使用。
所以......发布的答案是一个很好的属性解决方法,对于我使用 Money 作为元素的地方,我只是实现了 IXmlSerializable 来输出复合字段并在解析时重新拆分它。这样,不需要包装器,它就可以工作。
public struct Money : IXmlSerializable
{
public double Amount { get; set; }
public string CurrencyCode { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
return (null);
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
Boolean isEmptyElement = reader.IsEmptyElement; // (1)
reader.ReadStartElement();
if (!isEmptyElement) // (1)
{
var str = reader.ReadContentAsString();
string[] sa = str.Split(' ');
Amount = double.Parse(sa[0]);
CurrencyCode = sa[1];
reader.ReadEndElement();
}
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteString(Amount + " " + CurrencyCode);
}
}
Run Code Online (Sandbox Code Playgroud)
对于属性,发布的答案也有效,谢谢。
下面的代码可以解决这个问题:
public class Money
{
public decimal Amount { get; set; }
public string CurrencyCode { get; set; }
}
public class SomeClass
{
public SomeClass() { }
[XmlIgnore]
public Money WrappedMoney { get; set; }
[XmlAttribute]
public string moneyValue
{
get
{
return String.Format("{0:.##}{1}", WrappedMoney.Amount, WrappedMoney.CurrencyCode);
}
}
}
public class ParentClass
{
public SomeClass SomeClass {get; set;}
}
class Program
{
public static int Main(string[] args)
{
var parent = new ParentClass
{
SomeClass = new SomeClass
{
WrappedMoney = new Money { Amount = 1.25M, CurrencyCode = "USD" }
}
};
var serializer = new XmlSerializer(typeof(ParentClass));
using (var writer = new StreamWriter("output.xml"))
{
serializer.Serialize(writer, parent);
}
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
XML 输出为:
<?xml version="1.0" encoding="utf-8"?>
<ParentClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SomeClass moneyValue="1.25USD" />
</ParentClass>
Run Code Online (Sandbox Code Playgroud)