使用 xsd.exe 访问从 xml 生成的 class 项目

Access class item generated from xml using xsd.exe

好吧,我使用 .net xsd.exe 生成了一些 classes 来处理一些 xml 文件,目前没问题。我可以使用 XmlSerializaer 读取和反序列化 classes,并且可以毫无问题地读取大部分内容。

我的问题是当我到达某些地方时,例如下面的地方:

/// <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;
        }
    }
}

我可以访问 public 对象 "Item",但是我怎样才能更深入呢? 当我到达 ...Pis 时,我只能访问 "Item".

上述项目中的一个元素:

 /// <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;
        }
    }
}

我需要访问 TNFeInfNFeDetImpostoPISPISAliq 中的 public 字符串 vBC、pPis 和其他字符串 class。

这里是用来生成classes的XML的一部分(只是为了保存space删除了文档):

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

所以你有一个 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 生成这些成员。如果没有,您可以创建一个部分 class 来执行此操作:

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

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

    // ...
}

另见 Dilemma with XSD, Generics and C# Classes and