【发布时间】:2016-08-03 07:58:50
【问题描述】:
我有大量自动生成的类,这些类使用 .NET XmlSerializer 从 XML 序列化/反序列化。其中一些类包含 DateTime 属性。
我需要使用特定格式(例如“u”)序列化 所有 DateTime 属性。 :
System.DateTime.Now.ToString("u");
//returns something like "2008-06-15 21:15:07Z"
Deserialize 方法似乎适用于这种格式,但序列化不起作用 - 它只是给我硬编码格式 与我在托管系统中默认使用的格式相同(也许我可以通过更改线程设置来欺骗序列化程序?) (检查更新 #1)。
注意: 我已经检查了一些相关问题,并通过修改原始属性和添加新属性来解决它们。对我来说这是不可接受的,因为我必须进行大量修改。
- How to serialize Xml Date only from DateTime in C#
- Force XmlSerializer to serialize DateTime as 'YYYY-MM-DD hh:mm:ss'
以下是我用来测试此问题的示例测试类。
using System;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Globalization;
using System.IO;
namespace FunkyTests
{
[TestClass]
public class SerializationTests
{
[TestMethod]
public void FunkySerializationTest()
{
var date = DateTime.Now;
var dummy = new Dummy() { DummyProperty = date };
var xml = SerializeToXml(dummy);//serializes with "o" format
var expected = date.ToString("u", new CultureInfo("en-US"));//in this example I want "u" format
var actual = XDocument.Parse(xml).Descendants("DummyProperty").Single().Value;
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void FunkyDeserializationTest()
{
var date = DateTime.Now;
var dummy = new Dummy() { DummyProperty = date };
var xml = SerializeToXml(dummy);//serializes with "o" format
var deserializedDummy = DeserializeFromXml<Dummy>(xml);
Assert.AreEqual(dummy.DummyProperty, deserializedDummy.DummyProperty);
}
private static T DeserializeFromXml<T>(string xml)
{
using (var textReader = new StringReader(xml))
{
using (var reader = XmlReader.Create(textReader))
{
var serializer = new XmlSerializer(typeof(T));
var result = serializer.Deserialize(reader);
return (T)result;
}
}
}
private static string SerializeToXml<T>(T objectToSerialize)
{
var xml = new StringBuilder();
using (var writer = XmlWriter.Create(xml, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
var ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, objectToSerialize, ns);
}
return xml.ToString();
}
public class Dummy
{
public DateTime DummyProperty { get; set; }
}
}
}
有什么时髦的想法吗?
更新 #1: 我认为日期序列化取决于 Thread.CurrentCulture。如果我正确解释 XmlSerializer 代码,格式是硬编码的(感谢 ILSpy)。
// System.Xml.Serialization.XmlCustomFormatter
internal static string FromDateTime(DateTime value)
{
if (XmlCustomFormatter.Mode == DateTimeSerializationSection.DateTimeSerializationMode.Local)
{
return XmlConvert.ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz");
}
return XmlConvert.ToString(value, XmlDateTimeSerializationMode.RoundtripKind);
}
更新 #2: 我添加了一种测试方法,该方法使用 Alexander Petrov 提出的答案。它在断言 Ticks 时失败。根据Serialize DateTime as binary,问题出在 DateTime 的内部,是由于丢失了 DateTime 的“种类”引起的。有人建议使用DateTimeOffset,这导致了另一个序列化问题,在How can I XML Serialize a DateTimeOffset Property?中解释了
【问题讨论】:
-
见this(你已经提到过),你仅限于
XmlIgnoreAttribute(使用另一个属性例如string类型来序列化/反序列化DateTime属性)或IXmlSerializable(自定义序列化器,您可以在其中添加自己的属性,通过这些属性您可以为序列化器/反序列化器指定各种选项,包括数据格式)。如果你能找到与文化相关的XmlSerializer(我打赌应该有),那么你可以使用自定义DateTime格式创建自己的文化并使用它。 -
你的问题解决了吗?
标签: c# .net xml serialization format