Доступ к элементу класса, сгенерированному из xml, с помощью xsd.exe

Ну, я сгенерировал некоторые классы для работы с некоторыми XML-файлами, используя.net xsd.exe, пока никаких проблем. Я могу читать и отменять реализацию классов с помощью XmlSerializaer, и читать большинство из них без каких-либо проблем.

Моя проблема в том, когда я приезжаю в некоторые места, такие как один ниже:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.portalfiscal.inf.br/nfe")]
public partial class TNFeInfNFeDetImpostoPIS
{

    private object itemField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("PISAliq", typeof(TNFeInfNFeDetImpostoPISPISAliq))]
    [System.Xml.Serialization.XmlElementAttribute("PISNT", typeof(TNFeInfNFeDetImpostoPISPISNT))]
    [System.Xml.Serialization.XmlElementAttribute("PISOutr", typeof(TNFeInfNFeDetImpostoPISPISOutr))]
    [System.Xml.Serialization.XmlElementAttribute("PISQtde", typeof(TNFeInfNFeDetImpostoPISPISQtde))]
    public object Item
    {
        get
        {
            return this.itemField;
        }
        set
        {
            this.itemField = value;
        }
    }
}

Я могу получить доступ к общедоступному объекту "Предмет", но как я могу пойти глубже? И когда я добираюсь до... Пис, я могу получить доступ только к "Предмету".

Один из элементов из пункта выше:

 /// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.portalfiscal.inf.br/nfe")]
public partial class TNFeInfNFeDetImpostoPISPISAliq
{

    private TNFeInfNFeDetImpostoPISPISAliqCST cSTField;

    private string vBCField;

    private string pPISField;

    private string vPISField;

    /// <remarks/>
    public TNFeInfNFeDetImpostoPISPISAliqCST CST
    {
        get
        {
            return this.cSTField;
        }
        set
        {
            this.cSTField = value;
        }
    }

    /// <remarks/>
    public string vBC
    {
        get
        {
            return this.vBCField;
        }
        set
        {
            this.vBCField = value;
        }
    }

    /// <remarks/>
    public string pPIS
    {
        get
        {
            return this.pPISField;
        }
        set
        {
            this.pPISField = value;
        }
    }

    /// <remarks/>
    public string vPIS
    {
        get
        {
            return this.vPISField;
        }
        set
        {
            this.vPISField = value;
        }
    }
}

Мне нужно было бы получить доступ к общедоступной строке vBC, pPis и другим внутри класса TNFeInfNFeDetImpostoPISPISAliq.

Вот фрагмент XML, используемый для генерации классов (только что удалена документация для экономии места):

<xs:element minOccurs = "0" name="PIS">
    <xs:annotation>
        <xs:documentation>whatever</xs:documentation>
    </xs:annotation>
    <xs:complexType>
        <xs:choice>
            <xs:element name = "PISAliq" >
                <xs:annotation>
                    <xs:documentation>whatever;</xs:documentation>
                </xs:annotation>
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name = "CST" >
                            <xs:annotation>
                                <xs:documentation>whatever;</xs:documentation>
                            </xs:annotation>
                            <xs:simpleType>
                                <xs:restriction base="xs:string">
                                    <xs:whiteSpace value = "preserve" />
                                    <xs:enumeration value = "01" />
                                    <xs:enumeration value = "02" />
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>
                        <xs:element name = "vBC" type="TDec_1302">
                            <xs:annotation>
                                <xs:documentation>whatever</xs:documentation>
                            </xs:annotation>
                        </xs:element>

1 ответ

Решение

Итак, у вас есть Item свойство типа objectкоторый будет десериализован либо в TNFeInfNFeDetImpostoPISPISAliq или любой из трех других типов, помеченных [XmlElement("PIS...", typeof(...)] типы.

Затем вам нужно определить его тип во время выполнения:

var deserializedObjectAliq = deserialized.Item as TNFeInfNFeDetImpostoPISPISAliq;
if (deserializedObjectAliq != null)
{
    deserializedObjectAliq.WhatEver
}

var deserializedObjectNT = deserialized.Item as TNFeInfNFeDetImpostoPISPISNT;
if (deserializedObjectNT != null)
{
    deserializedObjectNT.WhatEver
}

// ...

Вы бы лучше создать члена в <xsd:choice> а не хранить его в objectтак что вы можете просто проверить if (deserializedObject.Aliq != null) { ... },

Я не уверен, что вы можете сказать, xsd.exe чтобы генерировать эти члены вместо. Если это не так, вы можете создать частичный класс, который делает это:

public partial class TNFeInfNFeDetImpostoPIS
{
    public TNFeInfNFeDetImpostoPISPISAliq Aliq
    {
        get
        {
            return Item as TNFeInfNFeDetImpostoPISPISAliq;
        }
    }       

    public TNFeInfNFeDetImpostoPISPISNT NT
    {
        get
        {
            return Item as TNFeInfNFeDetImpostoPISPISNT;
        }
    }

    // ...
}

См. Также Дилемма с классами XSD, Generics и C# и XSD.exe - Как инициализировать тип, созданный из xs: choice.

Другие вопросы по тегам