关于this question,我遇到了同样的问题。我使用基于SOAP的API来回发送数据,其中响应不符合标准,特别是使用空值。对于DateTime
,API将发回一个空字符串,如下所示:
<nextreview></nextreview>
导致反序列化时出现以下错误:
字符串''不是有效的AllXsd值。
所以我的想法是创建一个自定义Nullable类型NullableOrEmpty<T>
,实现IXMLSerializable
通过将空字符串转换为null来处理空字符串。问题是我只想处理空字符串的例外情况。我希望使用“默认”行为正常序列化和反序列化其他所有内容。如何在下面的代码中模拟序列化的默认行为?
public class NullableOrEmpty<T> : IXmlSerializable
where T : struct
{
public T? NullableValue { get; set; }
public T Value { get { return this.NullableValue.Value; } }
public bool HasValue { get { return this.NullableValue.HasValue; } }
...
public void ReadXml(XmlReader reader)
{
string xml = reader.ReadElementContentAsString();
if (string.IsNullOrEmpty(xml))
{
this.NullableValue = null;
}
else
{
//THIS SHOULD DO THE DEFAULT. THIS DOESN'T WORK. WHAT DO I DO??
//this.NullableValue = (T?)new XmlSerializer(typeof(T?)).Deserialize(reader);
}
}
public void WriteXml(XmlWriter writer)
{
//THIS SHOULD DO THE DEFAULT. THIS DOESN'T WORK. WHAT DO I DO??
//new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
}
}
当我说“这不起作用”时,它会专门生成以下错误消息,可能是因为它试图消耗不存在的东西:
XML文档中存在错误(63, 6)。
<lastreview xmlns=''>
不是 预期
这是一个XML片段。该错误是由birthdate
中的值引起的,因为在实际给出值的非例外情况下我没有正确使用它:
<udf4></udf4>
<udf3></udf3>
<birthdate>1978-05-24Z</birthdate>
<lastreview></lastreview>
<fulltime>1</fulltime>
任何想法或想法都表示赞赏。如果需要,我可以发布更多代码示例或测试出建议。谢谢!
答案 0 :(得分:3)
你可以在这做一件事,虽然可能更痛苦的是实现适配器模式,你从xml结果填充的对象只有string类型的属性,然后写一个转换器方法来填充你的'当目标属性为DateTime时,对象检查空字符串。它可能比实现自己的序列化器更容易。
答案 1 :(得分:0)
我不再使用这个类了(我需要第三方验证),但实际上我可以通过使用XmlConvert
帮助程序手动处理所有数据类型来使其工作:
public void ReadXml(XmlReader reader)
{
string xml = reader.ReadElementContentAsString();
if (string.IsNullOrEmpty(xml))
{
this.NullableValue = null;
}
else
{
if (this.NullableValue is bool)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToBoolean(xml), typeof(T?));
else if (this.NullableValue is byte)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToByte(xml), typeof(T?));
else if (this.NullableValue is char)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToChar(xml), typeof(T?));
else if (this.NullableValue is DateTime)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDateTime(xml), typeof(T?));
else if (this.NullableValue is decimal)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDecimal(xml), typeof(T?));
else if (this.NullableValue is double)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDouble(xml), typeof(T?));
else if (this.NullableValue is Guid)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToGuid(xml), typeof(T?));
else if (this.NullableValue is short)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt16(xml), typeof(T?));
else if (this.NullableValue is int)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt32(xml), typeof(T?));
else if (this.NullableValue is long)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt64(xml), typeof(T?));
else if (this.NullableValue is float)
this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToSingle(xml), typeof(T?));
}
}
public void WriteXml(XmlWriter writer)
{
new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
}