Как десериализовать XML Choice для правильного сложного типа - PullRequest
0 голосов
/ 17 апреля 2019

Как десериализовать возвращаемый объект в правильный тип класса?

Вот разметка XML с тремя вариантами выбора (SuccessType, WarningsType и ErrorsType):

<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 может быть нулевым.Вот как я приведу и обнаружу, существует ли 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 Ответ

0 голосов
/ 19 апреля 2019

Вот мое текущее решение - создайте универсальный метод, который возвращает запрошенный тип.

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
}
...