Поделиться через


Использование Visual Studio ModelBus в текстовом шаблоне

Если вы пишете текстовые шаблоны, которые считывают модель, содержащую ссылки на Visual Studio ModelBus, может потребоваться разрешить ссылки для доступа к целевым моделям. В этом случае необходимо адаптировать текстовые шаблоны и указанные на них языки (DSLs):

  • DSL, который является целевым объектом ссылок, должен иметь адаптер ModelBus, настроенный для доступа из текстовых шаблонов. Если вы также обращаетесь к DSL из другого кода, в дополнение к стандартному адаптеру ModelBus требуется перенастройка адаптера.

    Диспетчер адаптеров должен наследоваться от VsTextTemplatingModelingAdapterManager и должен иметь атрибут [HostSpecific(HostName)].

  • Шаблон должен наследоваться от ModelBusEnabledTextTransformation.

Примечание.

Если вы хотите считывать модели DSL, которые не содержат ссылки на ModelBus, можно использовать процессоры директив, созданные в проектах DSL. Дополнительные сведения см. в разделе "Доступ к моделям" из текстовых шаблонов.

Дополнительные сведения о текстовых шаблонах см. в разделе "Создание кода во время разработки" с помощью текстовых шаблонов T4.

Создание адаптера шины модели для доступа из текстовых шаблонов

Чтобы разрешить ссылку ModelBus в текстовом шаблоне, целевой DSL должен иметь совместимый адаптер. Текстовые шаблоны выполняются в отдельном домене приложения из редакторов документов Visual Studio, поэтому адаптер должен загружать модель вместо доступа к ней через DTE.

  1. Если целевое решение DSL не имеет проекта ModelBusAdapter , создайте его с помощью мастера расширения Modelbus:

    1. Скачайте и установите расширение Visual Studio ModelBus, если это еще не сделано. Дополнительные сведения см. в статье "Пакет SDK для визуализации и моделирования".

    2. Откройте файл определения DSL. Щелкните правой кнопкой мыши область конструктора и нажмите кнопку "Включить modelbus".

    3. В диалоговом окне выберите "Я хочу предоставить этот DSL" в ModelBus. Вы можете выбрать оба варианта, если вы хотите, чтобы этот DSL предоставлял свои модели и потреблял ссылки на другие dsLs.

    4. Щелкните OK. В решение DSL будет добавлен новый проект ModelBusAdapter.

    5. Нажмите кнопку "Преобразовать все шаблоны".

    6. Заново постройте решение.

  2. Если вы хотите получить доступ к DSL как из текстового шаблона, так и из другого кода, например команды, дублируете проект ModelBusAdapter :

    1. В Windows Обозреватель скопируйте и вставьте папку, содержащую ModelBusAdapter.csproj.

    2. Переименуйте файл проекта (например, на T4ModelBusAdapter.csproj).

    3. В Обозреватель решений щелкните правой кнопкой мыши узел решения, наведите указатель мыши на добавление и выберите пункт "Существующий проект". Найдите проект нового адаптера T4ModelBusAdapter.csproj.

    4. В каждом *.tt файле нового проекта измените пространство имен.

    5. Щелкните правой кнопкой мыши новый проект в Обозреватель решений и выберите пункт "Свойства". В редакторе свойств измените имена созданной сборки и пространства имен по умолчанию.

    6. В проекте DslPackage добавьте ссылку на новый проект адаптера, чтобы он ссылался на оба адаптера.

    7. В DslPackage\source.extension.tt добавьте строку, которая ссылается на проект нового адаптера.

      <MefComponent>|T4ModelBusAdapter|</MefComponent>
      
    8. Преобразование всех шаблонов и перестроение решения. Ошибки сборки не должны возникать.

  3. В проекте нового адаптера добавьте ссылки на следующие сборки:

    • Microsoft.VisualStudio.TextTemplating.11.0
    • Microsoft.VisualStudio.TextTemplating.Modeling.11.0
  4. В AdapterManager.tt:

    • Измените объявление AdapterManagerBase таким образом, чтобы он наследовал от VsTextTemplatingModelingAdapterManager.

      public partial class <#= dslName =>AdapterManagerBase :

      Microsoft.VisualStudio.TextTemplating.Modeling.VsTextTemplatingModelingAdapterManager { ...

    • В конце файла замените атрибут HostSpecific перед классом AdapterManager. Удалите следующую строку:

      [DslIntegration::HostSpecific(DslIntegrationShell::VsModelingAdapterManager.HostName)]

      Вставьте следующую строку:

      [Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]

      Этот атрибут фильтрует набор адаптеров, доступных при поиске адаптера потребителем modelbus.

  5. Преобразование всех шаблонов и перестроение решения. Ошибки сборки не должны возникать.

Создание текстового шаблона, который может разрешать ссылки modelBus

Как правило, вы начинаете с шаблона, который считывает и создает файлы из dsL источника. Этот шаблон использует директиву, созданную в исходном проекте DSL, для чтения файлов исходной модели таким образом, как описано в разделе "Доступ к моделям из текстовых шаблонов". Однако исходный DSL содержит ссылки ModelBus на "целевой" DSL. Поэтому необходимо включить код шаблона для разрешения ссылок и доступа к целевому DSL. Поэтому необходимо адаптировать шаблон, выполнив следующие действия.

  • Измените базовый класс шаблона на ModelBusEnabledTextTransformation.

  • Включите hostspecific="true" в директиву шаблона.

  • Добавьте ссылки на сборку в целевой DSL и его адаптер и включите ModelBus.

  • Директива, созданная в рамках целевого DSL, не требуется.

<#@ template debug="true" hostspecific="true" language="C#"
inherits="Microsoft.VisualStudio.TextTemplating.Modeling.ModelBusEnabledTextTransformation" #>
<#@ SourceDsl processor="SourceDslDirectiveProcessor" requires="fileName='Sample.source'" #>
<#@ output extension=".txt" #>
<#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0" #>
<#@ assembly name = "Company.TargetDsl.Dsl.dll" #>
<#@ assembly name = "Company.TargetDsl.T4ModelBusAdapter.dll" #>
<#@ assembly name = "System.Core" #>
<#@ import namespace="Microsoft.VisualStudio.Modeling.Integration" #>
<#@ import namespace="Company.TargetDsl" #>
<#@ import namespace="Company.TargetDsl.T4ModelBusAdapters" #>
<#@ import namespace="System.Linq" #>
<#
  SourceModelRoot source = this.ModelRoot; // Usual access to source model.
  // In the source DSL Definition, the root element has a model reference:
  using (TargetAdapter adapter = this.ModelBus.CreateAdapter(source.ModelReference) as TargetAdapter)
  {if (adapter != null)
   {
      // Get the root of the target model:
      TargetRoot target = adapter.ModelRoot;
    // The source DSL Definition has a class "SourceElement" embedded under the root.
    // (Let's assume they're all in the same model file):
    foreach (SourceElement sourceElement in source.Elements)
    {
      // In the source DSL Definition, each SourceElement has an MBR property:
      ModelBusReference elementReference = sourceElement.ReferenceToTarget;
      // Resolve the target model element:
      TargetElement element = adapter.ResolveElementReference<TargetElement>(elementReference);
#>
     The source <#= sourceElement.Name #> is linked to: <#= element.Name #> in target model: <#= target.Name #>.
<#
    }
  }}
  // Other useful code: this.Host.ResolvePath(filename) gets an absolute filename
  // from a path that is relative to the text template.
#>

При выполнении SourceDsl этого текстового шаблона директива загружает файл Sample.source. Шаблон может получить доступ к элементам этой модели, начиная с this.ModelRoot. Код может использовать классы домена и свойства этого DSL.

Кроме того, шаблон может разрешать ссылки ModelBus. Где ссылки указывают на целевую модель, директивы сборки позволяют коду использовать классы домена и свойства DSL этой модели.

  • Если вы не используете директиву, созданную проектом DSL, также следует включить следующее.

    <#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.11.0" #>
    <#@ assembly name = "Microsoft.VisualStudio.TextTemplating.Modeling.11.0" #>
    
  • Используется this.ModelBus для получения доступа к ModelBus.

Пошаговое руководство. Тестирование текстового шаблона, использующего ModelBus

В этом пошаговом руководстве выполните следующие действия.

  1. Создайте два DSL. Один DSL, потребитель, имеет ModelBusReference свойство, которое может ссылаться на другой DSL, поставщик.

  2. Создайте два адаптера ModelBus в поставщике: один для доступа к текстовым шаблонам, а другой — для обычного кода.

  3. Создайте модели экземпляров dsLs в одном экспериментальном проекте.

  4. Задайте свойство домена в одной модели, чтобы указать другую модель.

  5. Напишите обработчик двойного щелчка, который открывает модель, на которую указывает.

  6. Напишите текстовый шаблон, который может загрузить первую модель, следуйте ссылке на другую модель и прочитайте другую модель.

Создание DSL, доступного для ModelBus

  1. Создайте новое решение DSL. В этом примере выберите шаблон решения потока задач. Задайте для имени MBProvider языка имя и расширение имени файла для .provide.

  2. На схеме определения DSL щелкните правой кнопкой мыши пустую часть схемы, которая не находится в верхней части, а затем нажмите кнопку "Включить modelbus".

    Если вы не видите включение Modelbus, скачайте и установите расширение VMSDK ModelBus.

  3. В диалоговом окне "Включить модельбус" выберите "Предоставить этот DSL" в ModelBus и нажмите кнопку "ОК".

    Новый проект ModelBusAdapterдобавляется в решение.

Теперь у вас есть DSL, к которым можно получить доступ с помощью текстовых шаблонов с помощью ModelBus. Ссылки на него можно разрешить в коде команд, обработчиков событий или правил, которые работают в домене приложения редактора файлов модели. Однако текстовые шаблоны выполняются в отдельном домене приложения и не могут получить доступ к модели при изменении. Если вы хотите получить доступ к ссылкам ModelBus на этот DSL из текстового шаблона, необходимо иметь отдельный объект ModelBusAdapter.

Создание адаптера ModelBus, настроенного для текстовых шаблонов

  1. В проводник скопируйте и вставьте папку, содержащую ModelBusAdapter.csproj.

    Назовите папку T4ModelBusAdapter.

    Переименуйте файл проекта T4ModelBusAdapter.csproj.

  2. В Обозреватель решений добавьте T4ModelBusAdapter в решение МБ Provider. Щелкните правой кнопкой мыши узел решения, наведите указатель на пункт "Добавить" и выберите пункт " Существующий проект".

  3. Щелкните правой кнопкой мыши узел проекта T4ModelBusAdapter и выберите пункт "Свойства". В окне свойств проекта измените имя сборки и пространство Company.MBProvider.T4ModelBusAdaptersимен по умолчанию.

  4. В каждом файле *.tt в T4ModelBusAdapter вставьте "T4" в последнюю часть пространства имен, чтобы строка выглядела следующим образом.

    namespace <#= CodeGenerationUtilities.GetPackageNamespace(this.Dsl) #>.T4ModelBusAdapters

  5. DslPackage В проекте добавьте ссылку на T4ModelBusAdapterпроект.

  6. В DslPackage\source.extension.tt добавьте следующую строку в <Content>раздел .

    <MefComponent>|T4ModelBusAdapter|</MefComponent>

  7. T4ModelBusAdapter В проекте добавьте ссылку на: Microsoft.VisualStudio.TextTemplating.Modeling.11.0

  8. Откройте T4ModelBusAdapter\AdapterManager.tt:

    1. Измените базовый класс AdapterManagerBase на VsTextTemplatingModelingAdapterManager. Эта часть файла теперь похожа на следующую.

      namespace <#= CodeGenerationUtilities.GetPackageNamespace(this.Dsl) #>.T4ModelBusAdapters
      {
          /// <summary>
          /// Adapter manager base class (double derived pattern) for the <#= dslName #> Designer
          /// </summary>
          public partial class <#= dslName #>AdapterManagerBase
          : Microsoft.VisualStudio.TextTemplating.Modeling.VsTextTemplatingModelingAdapterManager
          {
      
    2. В конце файла вставьте следующий дополнительный атрибут перед классом AdapterManager.

      [Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]

      Результат выглядит следующим образом.

      /// <summary>
      /// ModelBus modeling adapter manager for a <#= dslName #>Adapter model adapter
      /// </summary>
      [Mef::Export(typeof(DslIntegration::ModelBusAdapterManager))]
      [Mef::ExportMetadata(DslIntegration::CompositionAttributes.AdapterIdKey,<#= dslName #>Adapter.AdapterId)]
      [DslIntegration::HostSpecific(DslIntegrationShell::VsModelingAdapterManager.HostName)]
      [Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]
      public partial class <#= dslName #>AdapterManager : <#= dslName #>AdapterManagerBase
      {
      }
      
  9. Щелкните "Преобразовать все шаблоны" в строке заголовка Обозреватель решений.

  10. Нажмите клавишу F5.

  11. Убедитесь, что DSL работает. Откройте экспериментальный проект Sample.provider. Закройте экспериментальный экземпляр Visual Studio.

    Ссылки ModelBus на этот DSL теперь можно разрешить в текстовых шаблонах, а также в обычном коде.

Создание DSL с помощью свойства домена Reference ModelBus

  1. Создайте новый DSL с помощью шаблона решения "Минимальный язык". Присвойте языку имя МБ Consumer и задайте для расширения имени файла значение ".consume".

  2. В проекте DSL добавьте ссылку на сборку DSL МБ Provider. Щелкните правой кнопкой мыши MBConsumer\Dsl\References и нажмите кнопку "Добавить ссылку". На вкладке "Обзор" найдитеMBProvider\Dsl\bin\Debug\Company.MBProvider.Dsl.dll

    Это позволяет создавать код, использующий другой DSL. Если вы хотите создать ссылки на несколько DSLs, добавьте их также.

  3. На схеме определения DSL щелкните правой кнопкой мыши схему и нажмите кнопку "Включить ModelBus". В диалоговом окне выберите "Включить этот DSL" для использования ModelBus.

  4. В классе ExampleElementдобавьте новое свойство MBRдомена и в окно свойств задайте для его типа ModelBusReferenceзначение.

  5. Щелкните правой кнопкой мыши свойство домена на схеме и выберите пункт "Изменить модельBusReference". В диалоговом окне выберите элемент модели.

    Задайте фильтр диалогового окна файла следующим образом.

    Provider File|*.provide

    Подстрока после "|" — это фильтр для диалогового окна выбора файла. Вы можете задать его, чтобы разрешить любые файлы с помощью *.*

    В списке типов элементов модели введите имена одного или нескольких классов домена в DSL поставщика (например, Company.МБProvider.Task). Они могут быть абстрактными классами. Если оставить список пустым, пользователь может задать ссылку на любой элемент.

  6. Закройте диалоговое окно и преобразуйте все шаблоны.

    Вы создали DSL, который может содержать ссылки на элементы в другом DSL.

Создание ссылки на ModelBus на другой файл в решении

  1. В решении МБ Consumer нажмите клавиши CTRL+F5. Экспериментальный экземпляр Visual Studio открывается в проекте МБ Consumer\Debugging.

  2. Добавьте копию Sample.provide в проект МБ Consumer\Debugging. Это необходимо, так как ссылка ModelBus должна ссылаться на файл в том же решении.

    1. Щелкните правой кнопкой мыши проект отладки, наведите указатель на "Добавить" и выберите пункт "Существующий элемент".

    2. В диалоговом окне "Добавление элемента" задайте для фильтра значение "Все файлы" (*.*).

    3. Перейдите к разделу MBProvider\Debugging\Sample.provide и нажмите кнопку "Добавить".

  3. Открыть Sample.consume.

  4. Щелкните одну фигуру примера и в окно свойств щелкните [...] в свойстве МБ R. В диалоговом окне нажмите кнопку "Обзор" и выберите .Sample.provide В окне элементов разверните тип Task и выберите один из элементов.

  5. Сохраните файл. (Не закрывайте экспериментальный экземпляр Visual Studio.)

    Вы создали модель, содержащую ссылку ModelBus на элемент в другой модели.

Разрешение ссылки modelBus в текстовом шаблоне

  1. В экспериментальном экземпляре Visual Studio откройте пример файла текстового шаблона. Задайте его содержимое следующим образом.

    <#@ template debug="true" hostspecific="true" language="C#"
    inherits="Microsoft.VisualStudio.TextTemplating.Modeling.ModelBusEnabledTextTransformation" #>
    <#@ MBConsumer processor="MBConsumerDirectiveProcessor" requires="fileName='Sample.consume'" #>
    <#@ output extension=".txt" #>
    <#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0" #>
    <#@ assembly name = "Company.MBProvider.Dsl.dll" #>
    <#@ import namespace="Microsoft.VisualStudio.Modeling.Integration" #>
    <#@ import namespace="Company.MBProvider" #>
    <#
      // Property provided by the Consumer directive processor:
      ExampleModel consumerModel = this.ExampleModel;
      // Iterate through Consumer model, listing the elements:
      foreach (ExampleElement element in consumerModel.Elements)
      {
    #>
       <#= element.Name #>
    <#
        if (element.MBR != null)
      using (ModelBusAdapter adapter = this.ModelBus.CreateAdapter(element.MBR))
      {
              // If we allowed multiple types or DSLs in the MBR, discover type here.
        Task task = adapter.ResolveElementReference<Task>(element.MBR);
    #>
            <#= element.Name #> is linked to Task: <#= task==null ? "(null)" : task.Name #>
    <#
          }
      }
    #>
    
    

    Обратите внимание на следующие аспекты:

    • hostSpecific Необходимо задать атрибуты inherits template директивы.

    • Модель потребителя осуществляется обычным образом с помощью обработчика директив, созданного в этом DSL.

    • Директивы сборки и импорта должны иметь доступ к ModelBus и типам DSL поставщика.

    • Если вы знаете, что многие МБ R связаны с одной и той же моделью, лучше вызывать CreateAdapter только один раз.

  2. Сохраните шаблон. Убедитесь, что полученный текстовый файл похож на следующий.

    ExampleElement1
    ExampleElement2
         ExampleElement2 is linked to Task: Task2
    

Разрешение ссылки modelBus в обработчике жестов

  1. Закройте экспериментальный экземпляр Visual Studio, если он запущен.

  2. Добавьте файл с именем МБ Consumer\Dsl\Custom.cs и задайте его содержимое следующим образом:

    namespace Company.MB2Consume
    {
      using Microsoft.VisualStudio.Modeling.Integration;
      using Company.MB3Provider;
    
      public partial class ExampleShape
      {
        public override void OnDoubleClick(Microsoft.VisualStudio.Modeling.Diagrams.DiagramPointEventArgs e)
        {
          base.OnDoubleClick(e);
          ExampleElement element = this.ModelElement as ExampleElement;
          if (element.MBR != null)
          {
            IModelBus modelbus = this.Store.GetService(typeof(SModelBus)) as IModelBus;
            using (ModelBusAdapter adapter = modelbus.CreateAdapter(element.MBR))
            {
              Task task = adapter.ResolveElementReference<Task>(element.MBR);
              // Open a window on this model:
              ModelBusView view = adapter.GetDefaultView();
              view.Show();
              view.SetSelection(element.MBR);
            }
          }
        }
      }
    }
    
  3. Нажмите клавиши CTRL+F5.

  4. В экспериментальном экземпляре Visual Studio откройте файл Debugging\Sample.consume.

  5. Дважды щелкните одну фигуру.

    Если в этом элементе задано значение МБ R, откроется ссылка и выбран элемент, на который ссылается ссылка.

Примечание.

Компонент Text Template Transformation (Преобразование текстовых шаблонов) автоматически устанавливается как часть рабочей нагрузки разработки расширений Visual Studio. Его также можно установить на вкладке Отдельные компоненты Visual Studio Installer в категории Пакеты SDK, библиотеки и платформы. Установите компонент Пакет SDK для моделирования со вкладки Отдельные компоненты.