Импортер .NET xsd создает не сериализуемый класс - PullRequest
6 голосов
/ 03 февраля 2010

Я использую импортер .NET XSD.EXE для генерации классов C # из коллекции файлов XSD.Когда я попытался сериализовать один из классов в XML, он потерпел неудачу ( InvalidOperationException ), и, когда я в него копался, я обнаружил, что один из созданных классов, похоже, неправильный.

Вот соответствующий XSD-код:

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

А вот код C #, сгенерированный из него:

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

Он сделал Warnings массивоммассив WarningType.Когда я пытаюсь сериализовать это в XML, я получаю исключение InvalidOperationException:

  • Невозможно создать временный класс (результат = 1).
  • ошибкаCS0030: невозможно преобразовать тип «WarningType []» в «WarningType»
  • ошибка CS0030: невозможно преобразовать тип «WarningType []» в «WarningType»
  • ошибка CS0029: невозможно неявное преобразование типа «WarningType'to' WarningType [] '
  • ошибка CS0029: невозможно неявно преобразовать тип' WarningType 'в' WarningType [] '

Но если я изменю сгенерированный код с WarningType[][] наWarningType[] затем он сериализуется нормально.

Если не отредактировать сгенерированный класс C # всякий раз, когда я его воссоздаю (что, будем надеяться, будет происходить реже), есть ли другое решение?Это ошибка в файле xsd.exe или XSD-файл неверен?Может быть, есть проблема в XmlSerializer?

Что я хочу - это код C #, который корректно сериализуется в XML и проверяется на соответствие XSD.Прямо сейчас зубчатый массив кажется неправильным, потому что, если я удаляю его, он генерирует XML.

Я использую Visual Studio 2008.

1 Ответ

4 голосов
/ 03 февраля 2010

В инструменте xsd.exe есть ошибки.Я не помню этот конкретный, но я помню, как находил проблемы с неровными массивами, и, возможно, это остается ошибкой.если вы хотите, вы можете использовать инструмент XsdObjbectGen , также от Microsoft, но выпущенный независимо и внеполосно из .NET SDK.

Одна вещь, которую вы могли бы сделать, это пойти в обратном направлении: написать код C #, затем сгенерировать схему с помощью xsd.exe и посмотреть, что отличается.Возможно, xsd.exe хочет, чтобы схема выглядела определенным образом, чтобы правильно генерировать правильный код для зубчатых массивов.


На самом деле, перечитав свой вопрос, вы никогда не сказали то, что действительно хотели.Вы хотите, чтобы SuccessType содержал массив массивов, или нет?

И это WarningsType или WarningType ?Есть некоторые разногласия между предоставленными фрагментами кода.


Предполагая, что вам нужен массив массивов, я написал этот код 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;
        }
    }
}

... и скомпилировал егов DLL.Затем я запустил xsd.exe в этой DLL-библиотеке и сгенерировал этот 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>

... и он туда и обратно.Если я затем запускаю xsd.exe в этой схеме, я получаю тип, который оборачивает массив массивов.

...