Расширяем UML для генерации XSD

в 5:19, , рубрики: .net, Visual Studio, метки: ,

Для .net разработчиков не секрет что существует Visual Studio, а в ней есть Architecture Modeling. С помощью этого инструмента отлично получается создавать диаграммы, визуализировать мысли, можно даже код сгенерировать. Для нас было важно связать то, что было «намоделировано» с реальным миром и данными. Как вы понимаете, модель в вакууме разработчикам не очень интересна.

Мы решили немного расширить описание модели, чтобы иметь возможность из неё сгенерировать артефакты, которые можно использовать вне Modeling Project. В нашем случае это были XSD схемы, которые описывают модели (контракты методов API). Можно было и WSDL генерировать, можно Java/C# классы, но мы остановились на xsd.

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

Visual Studio SDK

Чтобы писать расширения для uml нужно 2 компонента:

Visual Studio UML «API»

Все типы диаграмм, которые можно строить в Visual Studio, предоставляют свои объекты через унифицированные интерфейсы.
Набор их таков:

  • Microsoft.VisualStudio.Uml.Classes.IClass
  • Microsoft.VisualStudio.Uml.Classes.IDependency
  • Microsoft.VisualStudio.Uml.Classes.IEnumeration
  • Microsoft.VisualStudio.Uml.Classes.IInterface
  • Microsoft.VisualStudio.Uml.Classes.IOperation
  • Microsoft.VisualStudio.Uml.Classes.IPackage
  • Microsoft.VisualStudio.Uml.Classes.IPackageImport
  • Microsoft.VisualStudio.Uml.Classes.IProperty

Я думаю, что из их названий примерно понятно что это. Для диаграммы классов этот список map'ится прям один в один, а, например, для диаграммы компонентов сам компонент будет представлен как IClass, его интерфейсы — как IProperties и т.д. Смысл в том, что интерфейсы единообразны для разных типов моделей. Это хорошо, т.к. можно одинаково работать с разными типами диаграмм, но нас будут интересовать диаграммы классов.

Profile

Существует C#-profile, частный случай profile. В нем описано в виде xml, какие объекты какими метаданными на диаграмме могут быть описаны/расширены.
Пример: в UML модели Visual Studio существует диаграмма классов, в ней есть классы: их можно получить через интерфейс Microsoft.VisualStudio.Uml.Classes.IClass. В C# этому интерфейсу можно сопоставить и class, и struct. На uml диаграмме мы можем выбрать (указав C#-profile) будем ли мы считать UML_Class эквивалентным C# class или C# struct.
Сам C#-profile можно найти в папке C:Program Files (x86)Microsoft Visual Studio 11.0Common7IDEExtensionsMicrosoftArchitecture ToolsUmlProfiles
На него лучше посмотреть своими глазами — он не такой уж большой (строк 400).

Profile состоит из 3 секций:

  • Stereotypes. Простым языком, это то метаописание, которое можно закрепить за элементом UML модели. Например, class или атрибут класса.
  • Metaclasses — это то, какому интерфейсу из Microsoft.VisualStudio.Uml.Classes.* соответсвует стереотип. К примеру, C# struct/class соответсвуеют IClass, а IPackage соотвествует namespace в C#.
  • propertyTypes — какими типами представлено (строки, булевские значение и тп.)

Как работает генератор C# кода из UML.

На UML диаграмме рисуются создаются (ибо мы архитекторы, а не просто быдлокодеры) модели. Во всей диаграмме допускается использование определенного набора profiles, в частности C# profile. Затем у модели можно выбрать, какой stereotype из profile использовать. Потом можно задать к stereotype его свойства: например, у C# видимость класса (public/protected/private etc).
Разметку закончили.

К Visual Studio написано расширение (extension), которое добавляет кнопку «Generate Code».
Мы можем написать свои обработчики кнопок:

Жмем кнопку, вызывается прикладной код расширения и он уже генерирует код.
Внутри происходит следующее:

  • Из папки берутся C# t4 template C:Program Files (x86)Microsoft Visual Studio 11.0Common7IDEExtensionsMicrosoftArchitecture ToolsExtensibilityTemplatesText
  • На основе них генерируется код. Сам C# template, в целом, имеет понятную и тривиальную структуру: отрендерить все поля класса, все методы, атрибуты каждого метода. В общем, совсем не rocket science. Можно почитать этот код и суть вы уливите быстро. Сам шаблон — это C# код процентов на 80%, на оставшиеся 20% — тексты шаблонов.

Генерация XSD из схемы.

Что нам нужно чтобы схожим образом сгенерировать xsd схемы.

  • Создать Xsd.profile.
    Пример XSD.profile

    Расширяем UML для генерации XSD

    Пример создания profile, Кастомизация profile, Описание содержимого profile

  • Создать vsix расширение к Visual Studio.

    Расширяем UML для генерации XSD

  • В Visual studio в UML модели привязать profile к диаграмме
  • Классам сопоставить stereotypes из profile.

    Расширяем UML для генерации XSD

  • Создать расширение Visual Studio, которое отобразит кнопку “compile xsd schema” Расширяем UML для генерации XSD
    Здесь нужно чуть по подробнее остановиться, тк есть не всем известные атрибуты.
    Export — этот атрибут из MEF(Management Extensibility Framework). Он используется Visual Studio- как механизм загрузки и использования расширений. До версии vs2012 это MEF1. Не повторяйте мою ошибку с попыткой использовать последнюю версию- MEF2 ибо не заработает.VS видят на классе атрибут Export регистрирует класс в себе.

    Атрибут ClassDesignerExtension — этот атрибут один из комплекта атрибутов, по которым Visual Studio определяет на каких типах диаграмм это расширение можно использовать. Другие варианты ComponentDesignerExtension и тп. Этих атрибутов можно поставить и больше, но мне было достаточно одного.

    Import на свойстве DiagramContext — Он говорит Visual Studio что это свойство нужно инициализировать из MEF контейнера. Есть Dependency Injection через конструктор, а это DI через свойства.

    Остальной код- тривиален: получить все элементы IClass, сгруппировать их по IPackage.Name и далее для каждого пакета- вывести в файл.

  • Установить это расширение.
  • Написать обработчик, который по нажатии на кнопку сгенерирует xsd схемы. Нажать на кнопку Compile XSD (Название не принципиально)

    Расширяем UML для генерации XSD

    (Можно на t4 это сделать, но самый простой прототип проще получить конкатенацией строк, хотя t4, безусловно, правильнее.)

  • В итоге должно получиться примерно так:

    Расширяем UML для генерации XSD
    Расширяем UML для генерации XSD

P.S. У меня не было задачи сделать полную генерацию XSD схему- задача была показать как это делается в принципе.

Автор: SychevIgor

Источник

Поделиться

* - обязательные к заполнению поля