如果返回类型可能是错误或成功对象,如何反序列化XML

时间:2017-05-29 03:00:24

标签: c# xml serialization

我正在使用基于XML的API,因为它的根节点可以返回SuccessResponseErrorResponse

我使用下面的方法反序列化数据,但我不知道如何处理返回不是SuccessResponse的情况。 处理返回的XML不是预期格式的情况的最佳方法是什么?

我知道我可以采取黑客的方式,并寻找SuccessResponseErrorResponse的出现,但这感觉不对。

    TheIconicApiResult result = this.apiService.SendGetRequest("GetProducts", new List<AbstractParam>() { new FilterParam("live"), new LimitParam(5000) });
    IXmlSerialiser xmlSerialiser = new XmlSerialiser();
    var xmlBody = xmlSerialiser.ParseXML<SuccessResponse>(result.ResponseBody);

    public TObject ParseXML<TObject>(string xml)
    {
        using (TextReader reader = new StreamReader(GetMemoryStream(xml)))
        {
            XmlSerializer serialiser = new XmlSerializer(typeof(TObject));
            return (TObject)serialiser.Deserialize(reader);
        }
    }

1 个答案:

答案 0 :(得分:2)

如果您的XML流包含多种可能的文档类型之一,则可以为每种类型构造XmlSerializer并调用XmlSerializer.CanDeserialize(XmlReader)以连续测试是否可以将文档反序列化为该类型。此方法不会使XmlReader超过根元素,因此可以多次调用它而无需重新读取流。

例如,您可以引入以下扩展方法:

public static partial class XmlSerializerExtensions
{
    public static object DeserializePolymorphicXml(this string xml, params Type[] types)
    {
        using (var textReader = new StringReader(xml))
        {
            return textReader.DeserializePolymorphicXml(types);
        }
    }

    public static object DeserializePolymorphicXml(this TextReader textReader, params Type[] types)
    {
        if (textReader == null || types == null)
            throw new ArgumentNullException();
        var settings = new XmlReaderSettings { CloseInput = false }; // Let caller close the input.
        using (var xmlReader = XmlReader.Create(textReader, settings))
        {
            foreach (var type in types)
            {
                var serializer = new XmlSerializer(type);
                if (serializer.CanDeserialize(xmlReader))
                    return serializer.Deserialize(xmlReader);
            }
        }
        throw new XmlException("Invalid root type.");
    }
}

然后按如下方式使用:

var xmlBody = result.ResponseBody.DeserializePolymorphicXml(typeof(SuccessResponse), typeof(FailResponse));
if (xmlBody is SuccessResponse)
{
    // Handle successful response
}
else if (xmlBody is FailResponse)
{
    // Handle failed response
}
else
{
    // unknown response
    throw new InvalidOperationException("unknown response");
}

示例fiddle