我使用大量可序列化对象反序列化xml。 我已经读到,为了避免在 DateTime 中无效的 AllXsd 值,我必须创建一个帮助程序字符串属性,该属性将输入作为字符串处理并转换它。 即
[XmlIgnore]
public DateTime? DateUpdated { get; set; }
[XmlElement("updateDate")]
public string DateUpdatedAsText
{
set
{
if (!string.IsNullOrWhiteSpace(value))
{
try
{
DateUpdated = DateTime.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception) { }
}
}
get
{
return DateUpdated.HasValue ? DateUpdated.Value.ToString("yyyy-MM-ddTHH:mm:ss") : null;
}
}
这经过测试并且效果很好。然而。。。
我有 100 多个包含 DateTime 字段的实体,其中一些不止一个,这个解决方案不是很实用。我将不得不在所有这些中实现这一点,如果将来我想改变任何东西,我将不得不在所有这些中再次这样做。 如何声明通用自定义适配器来处理所有日期时间类型。在Java中,我可以这样做:
@XmlJavaTypeAdapter(CalendarXmlAdapter.class)
@Column(name = "updateDate")
private Calendar DateUpdated;
并在 CalendarXmlAdapter 中.class指定编组和取消编组
C# System.Xml.Serialization.XmlSerializer 是否有类似的解决方案?
提前致谢
编辑
解决方案:这是@dbc评论和@steve16351答案的组合。我使用了 CustomDateTime 类(在 ReadXML 中有一些小的更改,但并不重要(和字段 SomeDate 的声明(仍然是 DateTime? 类型(我像这样使用它
[XmlElement(ElementName = "updateDate", IsNullable = true, Type = typeof(CustomDateTime))]
public DateTime? DateUpdated { get; set; }
转换顺利进行
如果需要对反序列化进行更多控制,可以使用IXmlSerializable
。虽然您不能全局提供特定类型的自定义转换器,但据我所知XmlSerializer
,您可以编写一个代理DateTime
类,如下所示实现IXmlSerializable
,在我看来,这比字符串属性和相应的 DateTime 属性的解决方案更优雅;并且会减少对代码库的破坏。
下面是此类解决方案的示例。它还利用隐式运算符来避免在您自己的代码中与DateTime?
进行转换的需要。
class Program
{
static void Main(string[] args)
{
XmlSerializer s = new XmlSerializer(typeof(MyClass));
MyClass myClass = null;
using (var sr = new StringReader(@"<myXml><updateDate>20181008</updateDate><someProp>Hello, world</someProp></myXml>"))
myClass = s.Deserialize(sr) as MyClass;
DateTime? myValue = myClass.SomeDate;
Console.WriteLine($"{myClass.SomeDate}");
Console.ReadKey();
}
}
[XmlRoot("myXml")]
public class MyClass
{
[XmlElement("updateDate")]
public CustomDateTime SomeDate { get; set; }
[XmlElement("someProp")]
public string SomeProp { get; set; }
}
public class CustomDateTime : IXmlSerializable
{
public DateTime? _dateTime { get; set; }
private const string EXPECTED_FORMAT = "yyyyMMdd";
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
var elementContent = reader.ReadElementContentAsString();
_dateTime = String.IsNullOrWhiteSpace(elementContent) ? (DateTime?)null : DateTime.ParseExact(elementContent, EXPECTED_FORMAT, CultureInfo.InvariantCulture);
}
public void WriteXml(XmlWriter writer)
{
if (!_dateTime.HasValue) return;
writer.WriteString(_dateTime.Value.ToString(EXPECTED_FORMAT));
}
public static implicit operator DateTime? (CustomDateTime input)
{
return input._dateTime;
}
public static implicit operator CustomDateTime (DateTime input)
{
return new CustomDateTime() { _dateTime = input };
}
public override string ToString()
{
if (_dateTime == null) return null;
return _dateTime.Value.ToString();
}
}