如何将 XML Choice 反序列化为正确的复杂类型

Posted

技术标签:

【中文标题】如何将 XML Choice 反序列化为正确的复杂类型【英文标题】:How to deserialize XML Choice to the right Complex Type 【发布时间】:2019-09-07 11:45:11 【问题描述】:

如何将返回对象反序列化为正确的类类型?

这是定义了三个选项(SuccessType、WarningsType 和 ErrorsType)的 XML 标记:

<xs:element name="TopNode">
<xs:complexType>
    <xs:choice>
        <xs:sequence>
            <xs:element name="Success" type="SuccessType">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Success element.</xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="Warnings" type="WarningsType" minOccurs="0">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Warning element.</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:sequence>
            <xs:element name="Errors" type="ErrorsType">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Error types element.</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:choice>
</xs:complexType>

这是在c#中生成的类

public partial class TopNode 

    [System.Xml.Serialization.XmlElementAttribute("Errors", typeof(ErrorsType), Order=0)]
    [System.Xml.Serialization.XmlElementAttribute("Success", typeof(SuccessType), Order=0)]
    [System.Xml.Serialization.XmlElementAttribute("Warnings", typeof(WarningsType), Order=0)]
    public object[] Items 
        get 
            return this.itemsField;
        
        set 
            this.itemsField = value;
            this.RaisePropertyChanged("Items");
        
       

WarningsType 的出现次数可以为零。以下是我如何转换并查找 Web 服务返回的结果中是否存在 WarningsType。

var warningTypes = readResponse.TopNode.Items.FirstOrDefault(r => r.GetType() == typeof(NamespaceA.WarningsType)) as NamespaceA.WarningsType;
if (warningTypes != null)  // my code... 

如何消除搜索并将其转换为正确的类类型并使以下成为可能的需要?

var warningTypes = readResponse.TopNode.WarningsType;

【问题讨论】:

创建一些测试数据,然后序列化看看你得到了什么。架构显示三个不同的元素,您正在创建一个数组。 【参考方案1】:

这是我当前的解决方案 - 创建一个返回请求类型的泛型方法。

public partial class TopNode

    public T GetItem<T>()
    
        var result = Items.FirstOrDefault(r => r.GetType() == typeof(T));
        return (T)result;
    

    public List<T> GetItems<T>()
    
        var results = Items.Where(r => r.GetType() == typeof(T)).Select(r => (T)r).ToList();
        return (List<T>)results;
    

获取警告类型

var warningsType = readResponse.TopNode.GetItems<WarningsType>();

但我必须在使用前执行空测试

if (warningsType != null)

    // code here

【讨论】:

以上是关于如何将 XML Choice 反序列化为正确的复杂类型的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将复杂的 Swift 对象序列化/反序列化为 AWS Lambda 有效负载?

将 xml 反序列化为对象时出错:System.FormatException 输入字符串格式不正确

需要帮助将 XML 文件反序列化为对象 C#

使用 XmlSerializer 将 XML 反序列化为类型

如何将 XML 反序列化为 C# 中的对象? [复制]

如何将不同名称的 XML 节点反序列化为相同的基本类型