1

关于这个问题,我有同样的问题。我正在使用基于 SOAP 的 API 来回发送数据,其中响应不完全正确地遵循标准,特别是使用空值。对于DateTime,API 将返回一个空字符串,如下所示:

<nextreview></nextreview>

这导致反序列化时发生以下错误:

字符串 '' 不是有效的 AllXsd 值。

所以我的想法是创建一个自定义的 Nullable 类型,通过将其转换为 null 来NullableOrEmpty<T>实现IXMLSerializable处理空字符串。问题是我只想处理空字符串的例外情况。我想使用“默认”行为正常序列化和反序列化的所有其他内容。如何在下面的代码中模拟序列化的默认行为?

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>

任何想法或想法表示赞赏。如果需要,我可以发布更多代码示例或测试建议。谢谢!

4

2 回答 2

3

你可以在这里做的一件事,虽然它可能更痛苦的是实现适配器模式,你从 xml 结果填充的对象只有字符串类型的属性,然后编写一个转换器方法来填充你的“真实”对象当目标属性为 DateTime 时检查空字符串。它可能比实现自己的序列化器更容易。

于 2011-05-24T22:03:55.107 回答
0

我不再使用此类(我需要由第 3 方进行验证),但实际上我能够通过使用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);
}
于 2011-06-30T16:05:40.440 回答