Как создать перечисление xsd из классов С#?

У меня есть файл XSD (определение схемы XML), для которого требуется список перечисления (ограничение), состоящий из всех классов в заданном (ScoreService.App_Code.Entities) пространстве имен.

Я использую xsd.exe, автоматизированный в процессе сборки для выполнения задачи создания XSD-файла из рассматриваемых классов, и он правильно считывает их из сборки среды выполнения (MyBaseClass, MyClassA, ...), без проблем создавая следующий xsd-файл:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="MyBaseClass" nillable="true" type="MyBaseClass" />
  <xs:complexType name="MyBaseClass">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:int" />
    </xs:sequence>
  </xs:complexType>

  <xs:element name="MyClassA" nillable="true" type="MyClassA" />
  <xs:complexType name="MyClassA">
    <xs:complexContent mixed="false">
      <xs:extension base="MyBaseClass" />
    </xs:complexContent>
  </xs:complexType>

  ...

</xs:schema>

Но, насколько мне известно, я не смогу использовать это в перечислении xsd. Я предполагаю, что могу что-то сделать с атрибутами класса, чтобы контролировать внешний вид вывода XSD, но большинство атрибутов, которые я пробовал, применимы только к свойствам/членам.

Я хотел бы создать структуру XSD, похожую на:

<xs:simpleType name="ParamTypeRestriction">
  <xs:restriction base="xs:string">
    <xs:enumeration value="MyBaseClass"></xs:enumeration>
    <xs:enumeration value="MyClassA"></xs:enumeration>
    ...
  </xs:restriction>
</xs:simpleType>

Возможно ли это без дальнейшей автоматизации, такой как обработка сгенерированного файла xsd вручную? Если да, то как?


person John Weisz    schedule 03.12.2015    source источник
comment
Вы знаете, что членами перечисления являются строки, а не имена классов? Конечно, вы можете создать enum ParamTypeRestriction { MyBaseClass, MyClassA, ... } в коде, что приведет к желаемому xsd, но, возможно, это не то, что вы хотели бы сделать, потому что значения перечисления не имеют ничего общего с классами, за исключением того, что они имеют одинаковые имена.   -  person Martin    schedule 04.12.2015
comment
@Martin Что мне действительно нужно, так это чтобы имена всех классов (каждое из них — строка) в заданном пространстве имен были скомпилированы в перечисление в XSD. В основном, чтобы я мог автоматически обновлять список этих классов для файлов XML.   -  person John Weisz    schedule 04.12.2015
comment
Ну, если у вас есть один класс на файл, и файл назван в честь класса, вы могли бы использовать dir для создания файла с таким перечислением, но это было бы немного хакерски...   -  person Martin    schedule 04.12.2015
comment
Иерархия пространства имен в любом случае отражает настройку каталога, так что на самом деле это довольно приличная идея, и совсем не хакерская, в отношении согласованности кода. В конце концов, нужны только имена классов.   -  person John Weisz    schedule 04.12.2015


Ответы (1)


Я знаю, что нет продукта/библиотеки, которая могла бы делать то, что вам нужно. Однако с точки зрения кода должно быть относительно легко собрать что-то вместе, что дало бы вам именно то, что вам нужно.

Это то, что я бы сделал, чтобы ограничить количество предположений, которые мне пришлось бы ввести в отношении структуры файлов, видимости классов и т. д.

Во-первых, я бы составил список сборок, содержащих классы, которые вы хотите захватить.

Для каждой сборки в этом списке я получу список нужных мне типов. Есть много способов отразить сборку; предполагая, что сборки находятся в правильном контексте (т. е. все зависимости обнаруживаются), тогда что-то вроде этого сделает трюк довольно легко:

Assembly assembly = Assembly.Load(new AssemblyName() { CodeBase = path })

Получите список типов по мере необходимости:

Type[] types = assembly.GetExportedTypes();

Для каждого типа имя класса будет в формате type.Name, поскольку полное имя вас не интересует.

Используйте комбинированный список типов для создания простой схемы только с одним простым типом; используйте классы из System.Xml. Схема. Код будет примерно таким:

    void foo(IEnumerable<Type> types)
    {
        var rs = new XmlSchemaSimpleTypeRestriction
        {
            BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace)
        };
        foreach (var t in types)
        {
            rs.Facets.Add(new XmlSchemaEnumerationFacet {Value = t.Name});
        }
        var schema = new XmlSchema();
        schema.Items.Add(new XmlSchemaSimpleType
        {
            Name = "ParamTypeRestriction",
            Content = rs
        });
        schema.Write(...);
    }
person Petru Gardea    schedule 05.12.2015