2010-02-03 4 views
6

Sto utilizzando l'importatore .NET XSD.EXE per generare classi C# da una raccolta di file XSD. Quando ho provato a serializzare una delle classi in XML non è riuscito (InvalidOperationException), e quando l'ho scavato ho scoperto che una delle classi create sembra essere sbagliata..NET xsd importatore crea una classe non serializzabile

Ecco il codice XSD pertinente:

<xsd:complexType name="SuccessType"> 
    <xsd:annotation> 
     <xsd:documentation>Indicates in a response message that a request was successfully processed.</xsd:documentation> 
    </xsd:annotation> 
    <xsd:sequence> 
     <xsd:element ref="Warnings" minOccurs="0" maxOccurs="unbounded"/> 
    </xsd:sequence> 
</xsd:complexType> 
<!-- .. snip .. --> 
<xsd:element name="Warnings" type="WarningsType"> 
    <xsd:annotation> 
     <xsd:documentation>The processing status of a business message and any related warnings or informational messages.</xsd:documentation> 
    </xsd:annotation> 
</xsd:element> 
<!-- .. snip .. --> 
<xsd:complexType name="WarningsType"> 
    <xsd:annotation> 
     <xsd:documentation>A collection of warnings generated by the successful processing of a business message.</xsd:documentation> 
    </xsd:annotation> 
    <xsd:sequence> 
     <xsd:element ref="Warning" maxOccurs="unbounded"/> 
    </xsd:sequence> 
</xsd:complexType> 
<!-- .. snip .. --> 
<xsd:element name="Warning" type="WarningType"> 
    <xsd:annotation> 
     <xsd:documentation>Defines details of a warning that occurred during message processing.</xsd:documentation> 
    </xsd:annotation> 
</xsd:element> 
<!-- .. snip .. --> 
<xsd:complexType name="WarningType"> 
    <xsd:annotation> 
     <xsd:documentation>Defines details of a warning that occurred during message processing.</xsd:documentation> 
    </xsd:annotation> 
    <xsd:sequence> 
     <xsd:element ref="WarningCategory"/> 
     <xsd:element ref="WarningCode"/> 
     <xsd:element ref="WarningShortMessage"/> 
     <xsd:element ref="WarningMessage"/> 
    </xsd:sequence> 
</xsd:complexType> 

Ed ecco il codice C# generato da esso:

public partial class SuccessType 
{ 

    private WarningType[][] warningsField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlArrayItemAttribute("Warning", typeof(WarningType), IsNullable = false)] 
    public WarningType[][] Warnings 
    { 
     get 
     { 
      return this.warningsField; 
     } 
     set 
     { 
      this.warningsField = value; 
     } 
    } 
} 

Si fece Warnings una matrice di una matrice di WarningType. Quando tento di serializzare che a XML ricevo un'eccezione InvalidOperationException:

  • Impossibile generare una classe temporanea (risultato = 1).
  • errore CS0030: Impossibile convertire il tipo 'WarningType []' a 'WarningType'
  • errore CS0030: Impossibile convertire il tipo 'WarningType []' a 'WarningType'
  • errore CS0029: Impossibile convertire implicitamente il tipo 'WarningType' a 'WarningType []'
  • errore CS0029: Impossibile convertire implicitamente il tipo 'WarningType' a 'WarningType []'

Ma se cambio il codice generato WarningType[][]-WarningType[] allora serializza bene.

In mancanza di modifica della classe C# generata ogni volta che rigenera questo (che si spera sia meno frequente in avanti), c'è qualche altra soluzione? Si tratta di un bug in xsd.exe o il file XSD è errato? Forse c'è un problema in XmlSerializer?

Quello che voglio è il codice C# che serializza correttamente in XML che viene convalidato rispetto all'XSD. In questo momento l'array frastagliato sembra essere sbagliato perché se lo rimuovo, allora genera l'XML.

Sto usando Visual Studio 2008.

+0

Credo che questo sia un bug noto che non sarà risolto. Vedere https://connect.microsoft.com/VisualStudio/feedback/details/362727/xsd-exe-incorrect-class-generated-for-abstract-type-with-derived-types per un altro bug XSD che dicono non sarà fisso. –

+0

@John Saunders - Bugger, questo è quello che ho capito. C'è una buona alternativa a XSD.exe che conosci? –

+0

Il problema esiste ancora in .NET 4.5.1 – yW0K5o

risposta

4

ci sono bug nello strumento xsd.exe. Non ricordo questo particolare, ma ricordo di aver riscontrato problemi con gli array frastagliati, ed è possibile che questo rimanga un bug. se lo desideri, puoi utilizzare lo strumento XsdObjbectGen, anche da Microsoft, ma rilasciato indipendentemente e fuori banda da .NET SDK.

Una cosa che si potrebbe fare è andare nella direzione opposta: scrivere il codice C#, quindi generare lo schema con xsd.exe e vedere cosa è diverso. È possibile che xsd.exe desideri che lo schema appaia in un modo particolare, al fine di generare correttamente il codice corretto per gli array seghettati.


In realtà, dopo aver riletto la tua domanda, non hai mai detto quello che volevi davvero. Vuoi che SuccessType contenga un array di array, o no?

Ed è WarningsType o WarningType? C'è qualche disaccordo tra i codici tagliati che hai fornito.


Supponendo che si voleva la matrice-di-array, ho scritto questo codice C#:

public class WarningType 
{ 
    public String oof; 
} 


public partial class SuccessType 
{ 
    private WarningType[][] warningsField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlArrayItemAttribute("Warning", typeof(WarningType[]), IsNullable = false)] 
    public WarningType[][] Warnings 
    { 
     get 
     { 
      return this.warningsField; 
     } 
     set 
     { 
      this.warningsField = value; 
     } 
    } 
} 

... poi compilato in una DLL. Poi xsd.exe mi sono imbattuto in quella DLL, e hanno generato questo XSD:

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="WarningType" nillable="true" type="WarningType" /> 
    <xs:complexType name="WarningType"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="1" name="oof" type="xs:string" /> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:element name="SuccessType" nillable="true" type="SuccessType" /> 
    <xs:complexType name="SuccessType"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="1" name="Warnings" type="ArrayOfArrayOfWarningType" /> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="ArrayOfArrayOfWarningType"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="unbounded" name="Warning" type="ArrayOfWarningType" /> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="ArrayOfWarningType"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="unbounded" name="WarningType" nillable="true" type="WarningType" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

... ed è andata e ritorno. Se dunque io corro xsd.exe su questo schema, ho un tipo che avvolge una matrice-di-array.

+0

Ho aggiornato la mia domanda per essere più chiari. Sai dove posso trovare XSDObjectGen? –

+0

xsdobjectgen: http://www.microsoft.com/downloads/details.aspx?familyid=89e6b1e5-f66c-4a4d-933b-46222bb01eb0&displaylang=en – Cheeso

+0

Esiste una versione che funziona con qualcosa oltre .NET 1.1? Non riesco nemmeno a installarlo. Ho intenzione di zeppo questo fino a un bug: https://connect.microsoft.com/VisualStudio/feedback/details/362727/xsd-exe-incorrect-class-generated-for-abstract-type-with-derived-types –