Utilisation de Visual Studio ModelBus dans un modèle de texte

Si vous écrivez des modèles de texte qui lisent un modèle contenant des références Visual Studio ModelBus, vous pouvez résoudre les références pour accéder aux modèles cibles. Dans ce cas, vous devez adapter les modèles de texte et les langages dédiés (DSL) référencés :

  • Le DSL qui est la cible des références doit avoir un adaptateur ModelBus configuré pour être accessible par les modèles de texte. Si vous accédez également au DSL à partir d’un autre code, l’adaptateur reconfiguré est nécessaire en plus de l’adaptateur ModelBus standard.

    Le gestionnaire d’adaptateurs doit hériter de VsTextTemplatingModelingAdapterManager et avoir l’attribut [HostSpecific(HostName)].

  • Le modèle doit hériter de ModelBusEnabledTextTransformation.

Notes

Si vous souhaitez lire des modèles DSL qui ne contiennent pas de références ModelBus, vous pouvez utiliser les processeurs de directive générés dans vos projets DSL. Pour plus d’informations, consultez Accès aux modèles à partir de modèles de texte.

Pour plus d’informations sur les modèles de texte, consultez Génération de code au moment de la conception avec des modèles de texte T4.

Créer un adaptateur ModelBus pour que le DSL soit accessible par les modèles de texte

Pour résoudre une référence ModelBus dans un modèle de texte, le DSL cible doit avoir un adaptateur compatible. Les modèles de texte s’exécutent dans un AppDomain distinct des éditeurs de documents Visual Studio. Par conséquent, l’adaptateur doit charger le modèle au lieu d’y accéder à travers DTE.

  1. Si la solution DSL cible n’a pas de projet ModelBusAdapter, créez-en un avec l’Assistant Extension ModelBus :

    1. Téléchargez et installez l’extension Visual Studio ModelBus, si vous ne l’avez pas déjà fait. Pour plus d’informations, consultez Visualization and Modeling SDK.

    2. Ouvrez le fichier de définition DSL. Cliquez avec le bouton droit sur l’aire de conception, puis cliquez sur Activer ModelBus.

    3. Dans la boîte de dialogue, sélectionnez Je veux exposer ce DSL au ModelBus. Vous pouvez sélectionner les deux options si vous voulez que ce DSL expose ses modèles et consomme des références à d’autres DSL.

    4. Cliquez sur OK. Un nouveau projet « ModelBusAdapter » vient s'ajouter à la solution DSL.

    5. Cliquez sur Transformer tous les modèles.

    6. Régénérez la solution.

  2. Si vous souhaitez accéder au DSL à partir d’un modèle de texte et d’un autre code, comme une commande, dupliquez le projet ModelBusAdapter :

    1. Dans l’Explorateur Windows, copiez et collez le dossier qui contient ModelBusAdapter.csproj.

    2. Renommez le fichier projet (par exemple, T4ModelBusAdapter.csproj).

    3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, pointez sur Ajouter, puis cliquez sur Projet existant. Recherchez le nouveau projet d’adaptateur, T4ModelBusAdapter.csproj.

    4. Dans chaque fichier *.tt du nouveau projet, changez l’espace de noms.

    5. Cliquez avec le bouton droit sur le projet dans l’Explorateur de solutions, puis cliquez sur Propriétés. Dans l’éditeur de propriétés, changez les noms de l’assembly généré et de l’espace de noms par défaut.

    6. Dans le projet DslPackage, ajoutez une référence au nouveau projet d’adaptateur afin qu’il ait des références aux deux adaptateurs.

    7. Dans DslPackage\source.extension.tt, ajoutez une ligne qui référence votre nouveau projet d’adaptateur.

      <MefComponent>|T4ModelBusAdapter|</MefComponent>
      
    8. Transformez tous les modèles et regénérez la solution. Aucune erreur de génération ne doit se produire.

  3. Dans le nouveau projet d’adaptateur, ajoutez des références aux assemblys suivants :

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

    • Changez la déclaration d’AdapterManagerBase afin qu’elle hérite de VsTextTemplatingModelingAdapterManager.

      public partial class <#= dslName =>AdapterManagerBase :

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

    • Vers la fin du fichier, remplacez l’attribut HostSpecific avant la classe AdapterManager. Supprimez la ligne suivante :

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

      Insérez la ligne suivante :

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

      Cet attribut filtre l’ensemble d’adaptateurs disponible quand un consommateur ModelBus recherche un adaptateur.

  5. Transformez tous les modèles et regénérez la solution. Aucune erreur de génération ne doit se produire.

Écrire un modèle de texte pouvant résoudre les références ModelBus

En règle générale, vous commencez par un modèle qui lit et génère des fichiers à partir d’un DSL « source ». Ce modèle utilise la directive générée dans le projet DSL source pour lire les fichiers de modèle sources de la manière décrite dans Accès aux modèles à partir de modèles de texte. Toutefois, le DSL source contient des références ModelBus à un DSL « cible ». Vous souhaitez donc activer le code du modèle pour résoudre les références et accéder au DSL cible. Vous devez donc adapter le modèle en suivant ces étapes :

  • Remplacez la classe de base du modèle par ModelBusEnabledTextTransformation.

  • Ajoutez hostspecific="true" dans la directive de modèle.

  • Ajoutez des références d’assembly au DSL cible et à son adaptateur, et activez ModelBus.

  • Vous n’avez pas besoin de la directive générée dans le cadre du DSL cible.

<#@ 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.
#>

Quand ce modèle de texte est exécuté, la directive SourceDsl charge le fichier Sample.source. Le modèle peut accéder aux éléments de ce modèle, en commençant par this.ModelRoot. Le code peut utiliser les classes de domaine et les propriétés de ce DSL.

Par ailleurs, le modèle peut résoudre les références ModelBus. Quand les références pointent vers le modèle cible, les directives d’assembly permettent au code d’utiliser les classes de domaine et les propriétés du DSL de ce modèle.

  • Si vous n’utilisez pas de directive générée par un projet DSL, vous devez également ajouter les éléments suivants.

    <#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.11.0" #>
    <#@ assembly name = "Microsoft.VisualStudio.TextTemplating.Modeling.11.0" #>
    
  • Utilisez this.ModelBus pour obtenir l’accès à ModelBus.

Procédure pas à pas : Test d’un modèle de texte qui utilise ModelBus

Dans cette procédure pas à pas, vous suivez ces étapes :

  1. Construisez deux DSL. Un DSL, le consommateur, a une propriété ModelBusReference qui peut référencer l’autre DSL, le fournisseur.

  2. Créez deux adaptateurs ModelBus dans le fournisseur : un pour donner l’accès aux modèles de texte, l’autre pour le code ordinaire.

  3. Créez des modèles d’instance des DSL dans un projet expérimental.

  4. Définissez une propriété de domaine dans un modèle pour qu’elle pointe vers l’autre modèle.

  5. Écrivez un gestionnaire de double-clic qui ouvre le modèle ciblé par le pointage.

  6. Écrivez un modèle de texte qui peut charger le premier modèle, suivre la référence à l’autre modèle et lire l’autre modèle.

Construire un DSL accessible à ModelBus

  1. Créez une solution DSL. Pour cet exemple, sélectionnez le modèle de solution Task Flow. Définissez le nom du langage sur MBProvider et l’extension de nom de fichier sur « .provide ».

  2. Dans le diagramme de définition DSL, cliquez avec le bouton droit sur une partie vide du diagramme éloignée de la partie supérieure, puis cliquez sur Activer ModelBus.

    Si vous ne voyez pas Activer Modelbus, téléchargez et installez l’extension VMSDK ModelBus.

  3. Dans la boîte de dialogue Activer ModelBus, sélectionnez Exposer ce DSL au ModelBus, puis cliquez sur OK.

    Un nouveau projet, ModelBusAdapter, est ajouté à la solution.

Vous avez maintenant un DSL accessible par les modèles de texte à travers ModelBus. Les références au DSL peuvent être résolues dans le code de commandes, de gestionnaires d’événements ou de règles, tous fonctionnant dans l’AppDomain de l’éditeur de fichier de modèle. Toutefois, les modèles de texte s’exécutent dans un AppDomain distinct et ne peuvent pas accéder à un modèle quand il est modifié. Si vous souhaitez accéder aux références ModelBus vers ce DSL à partir d’un modèle de texte, vous devez avoir un ModelBusAdapter distinct.

Créer un adaptateur ModelBus configuré pour les modèles de texte

  1. Dans l’Explorateur de fichiers, copiez et collez le dossier qui contient ModelBusAdapter.csproj.

    Nommez le dossier T4ModelBusAdapter.

    Renommez le fichier projet T4ModelBusAdapter.csproj.

  2. Dans l’Explorateur de solutions, ajoutez T4ModelBusAdapter à la solution MBProvider. Cliquez avec le bouton droit sur le nœud de la solution, pointez sur Ajouter, puis cliquez sur Projet existant.

  3. Cliquez avec le bouton droit sur le nœud du projet T4ModelBusAdapter, puis cliquez sur Propriétés. Dans la fenêtre Propriétés du projet, remplacez le Nom de l’assembly et l’Espace de noms par défaut par Company.MBProvider.T4ModelBusAdapters.

  4. Dans chaque fichier *.tt de T4ModelBusAdapter, insérez « T4 » dans la dernière partie de l’espace de noms, afin que la ligne ressemble à ce qui suit.

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

  5. Dans le projet DslPackage, ajoutez une référence de projet à T4ModelBusAdapter.

  6. Dans DslPackage\source.extension.tt, ajoutez la ligne suivante sous <Content>.

    <MefComponent>|T4ModelBusAdapter|</MefComponent>

  7. Dans le projet T4ModelBusAdapter, ajoutez une référence à : Microsoft.VisualStudio.TextTemplating.Modeling.11.0

  8. Ouvrez T4ModelBusAdapter\AdapterManager.tt :

    1. Remplacez la classe de base AdapterManagerBase par VsTextTemplatingModelingAdapterManager. Cette partie du fichier ressemble maintenant à ce qui suit.

      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. Vers la fin du fichier, insérez l’attribut supplémentaire suivant devant la classe AdapterManager.

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

      Le résultat ressemble à ce qui suit.

      /// <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. Cliquez sur Transformer tous les modèles dans la barre d’outils de l’Explorateur de solutions.

  10. Appuyez sur F5.

  11. Vérifiez que le DSL fonctionne. Dans le projet expérimental, ouvrez Sample.provider. Fermez l’instance expérimentale de Visual Studio.

    Les références ModelBus à ce DSL peuvent désormais être résolues dans les modèles de texte et également dans le code ordinaire.

Construire un DSL avec une propriété de domaine de référence ModelBus

  1. Créez un DSL en utilisant le modèle de solution Minimal Language. Nommez le langage MBConsumer et définissez l’extension de nom de fichier sur « .consume ».

  2. Dans le projet DSL, ajoutez une référence à l’assembly DSL MBProvider. Cliquez avec le bouton droit sur MBConsumer\Dsl\References, puis cliquez sur Ajouter une référence. Sous l’onglet Parcourir, localisez MBProvider\Dsl\bin\Debug\Company.MBProvider.Dsl.dll

    Cela vous permet de créer du code qui utilise l’autre DSL. Si vous souhaitez créer des références à plusieurs DSL, ajoutez-les également.

  3. Dans le diagramme de définition DSL, cliquez avec le bouton droit sur le diagramme, puis cliquez sur Activer ModelBus. Dans la boîte de dialogue, sélectionnez Activer ce DSL pour consommer le ModelBus.

  4. Dans la classe ExampleElement, ajoutez une nouvelle propriété de domaine MBR et, dans la fenêtre Propriétés, définissez son type sur ModelBusReference.

  5. Cliquez avec le bouton droit sur la propriété de domaine dans le diagramme, puis cliquez sur Modifier les propriétés propres à ModelBusReference. Dans la boîte de dialogue, sélectionnez un élément de modèle.

    Définissez le filtre de la boîte de dialogue de fichiers sur ce qui suit.

    Provider File|*.provide

    La sous-chaîne après « | » est un filtre pour la boîte de dialogue de sélection de fichier. Vous pouvez le définir sur *.* pour autoriser tous les fichiers

    Dans la liste Type d’élément de modèle, entrez les noms d’une ou de plusieurs classes de domaine dans le DSL fournisseur (par exemple, Company.MBProvider.Task). Il peut s’agir de classes abstraites. Si vous laissez la liste vide, l’utilisateur peut définir la référence sur n’importe quel élément.

  6. Fermez la boîte de dialogue et transformez tous les modèles.

    Vous avez créé un DSL qui peut contenir des références à des éléments dans un autre DSL.

Créer une référence ModelBus vers un autre fichier dans la solution

  1. Dans la solution MBConsumer, appuyez sur Ctrl+F5. Une instance expérimentale de Visual Studio s’ouvre dans le projet MBConsumer\Debugging.

  2. Ajoutez une copie de Sample.provide au projet MBConsumer\Debugging. Cela est nécessaire, car une référence ModelBus doit référencer un fichier dans la même solution.

    1. Cliquez avec le bouton droit sur le projet Debugging, pointez sur Ajouter, puis cliquez sur Élément existant.

    2. Dans la boîte de dialogue Ajouter un élément, définissez le filtre sur Tous les fichiers (*.*).

    3. Accédez à MBProvider\Debugging\Sample.provide, puis cliquez sur Ajouter.

  3. Ouvrez Sample.consume.

  4. Cliquez sur un exemple de forme et, dans la fenêtre Propriétés, cliquez sur [...] dans la propriété MBR. Dans la boîte de dialogue, cliquez sur Parcourir et sélectionnez Sample.provide. Dans la fenêtre des éléments, développez le type Tâche et sélectionnez un des éléments.

  5. Enregistrez le fichier . (Ne fermez pas encore l’instance expérimentale de Visual Studio.)

    Vous avez créé un modèle qui contient une référence ModelBus à un élément dans un autre modèle.

Résoudre une référence ModelBus dans un modèle de texte

  1. Dans l’instance expérimentale de Visual Studio, ouvrez un exemple de fichier de modèle de texte. Définissez son contenu de la façon suivante.

    <#@ 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 #>
    <#
          }
      }
    #>
    
    

    Notez les points suivants :

    • Les attributs hostSpecific et inherits de la directive template doivent être définis.

    • Le modèle de consommateur est accessible de la manière habituelle à travers le processeur de directive qui a été généré dans ce DSL.

    • Les directives d’assembly et d’importation doivent pouvoir accéder à ModelBus et aux types du DSL fournisseur.

    • Si vous savez que de nombreuses MBR sont liées au même modèle, il est préférable d’appeler CreateAdapter une seule fois.

  2. Enregistrez le modèle. Vérifiez que le fichier texte résultant ressemble à ce qui suit.

    ExampleElement1
    ExampleElement2
         ExampleElement2 is linked to Task: Task2
    

Résoudre une référence ModelBus dans un gestionnaire de mouvements

  1. Fermez l’instance expérimentale de Visual Studio, si elle est en cours d’exécution.

  2. Ajoutez un fichier nommé MBConsumer\Dsl\Custom.cs et définissez son contenu de la façon suivante :

    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. Appuyez sur Ctrl+F5.

  4. Dans l’instance expérimentale de Visual Studio, ouvrez Debugging\Sample.consume.

  5. Double-cliquez sur une forme.

    Si vous avez défini la MBR sur cet élément, le modèle référencé s’ouvre et l’élément référencé est sélectionné.

Notes

Le composant Transformation de modèle de texte est automatiquement installé dans le cadre de la charge de travail Développement d’extensions Visual Studio. Vous pouvez aussi l’installer à partir de l’onglet Composants individuels de Visual Studio Installer, sous la catégorie SDK, bibliothèques et frameworks. Installez le composant Modeling SDK à partir de l’onglet Composants individuels.