Partager via


Comment : répondre à des modifications dans un modèle UML

Vous pouvez écrire du code qui est exécuté chaque fois qu'une modification se produit dans un modèle UML dans Visual Studio. Il répondra également aux modifications apportées directement par l'utilisateur et par d'autres extensions Visual Studio.

Avertissement

Cette fonctionnalité n'est pas prise en charge directement par l'API d'extension UML. Par conséquent, vous devez utiliser des techniques légèrement plus inhabituelles. Le code nécessaire est fourni dans cette rubrique. Toutefois, il peut arriver que des effets inattendus se produisent dans certains cas. Il est également possible que les futures modifications dans l'implémentation Visual Studio d'UML invalident les techniques décrites dans cette rubrique.

Pour utiliser les techniques décrites dans cette rubrique, il est utile de se familiariser avec le kit de développement logiciel Visualization and Modeling SDK (VMSDK), qui permet l'implémentation des outils UML. Pour plus d'informations, consultez Visualisation et modélisation du kit de développement logiciel (SDK) - Langages spécifiques à un domaine.

Dans cette rubrique :

  • Création d'un projet d'extension UML

  • Événements et règles

  • Définition d'événements

  • Exemple : Coloration de classes d'après des stéréotypes à l'aide d'événements

  • Définition de règles

  • Exemple : Coloration de classes d'après des stéréotypes à l'aide de règles

  • Exemple : Associations bidirectionnelles par défaut

  • Modèle de noyau et modèle Vue

Création d'un projet d'extension UML

Dans de nombreux cas, vous ajouterez un gestionnaire d'événements à une extension qui implémente déjà une commande ou le gestionnaire de mouvements. Vous pouvez alors ajouter le code décrit ici au même projet Visual Studio. Pour plus d'informations, consultez Comment : définir une commande de menu sur un diagramme de modélisation et Comment : définir un gestionnaire déposer et double-cliquer sur un diagramme de modélisation.

Si vous voulez créer votre gestionnaire d'événements dans une extension Visual Studio séparée, commencez par créer un projet de validation UML. Dans la boîte de dialogue Nouveau projet, cliquez sur Projets de modélisation, puis sélectionnez Extension de validation de modèle. Vous pouvez également suivre la procédure Définition d'une extension de validation dans Comment : définir des contraintes de validation pour les modèles UML.

Vous devez ajouter les références suivantes à votre projet :

  • \Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Uml.dll

  • Microsoft.VisualStudio.ArchitectureTools.Extensibility.dll

  • Microsoft.VisualStudio.Modeling.Sdk.10.0dll

  • Microsoft.VisualStudio.Modeling.Sdk.Diagrams.10.0.dll

  • Microsoft.VisualStudio.Uml.Interfaces.dll

Événements et règles

VMSDK fournit deux méthodes principales de détection des modifications dans le magasin :

  • Un gestionnaire d'événements répond à une modification après la fin de la transaction pendant laquelle la modification s'est produite. Les gestionnaires d'événements sont généralement utilisés pour propager des modifications à l'extérieur du modèle, aux interfaces utilisateur, aux fichiers ou aux bases de données. Vous pouvez également écrire un gestionnaire d'événements qui apporte une modification supplémentaire au modèle dans une nouvelle transaction.

    Une règle répond à une modification dans la transaction pendant laquelle la modification s'est produite. En général, les règles sont utilisées pour propager des modifications à l'intérieur du modèle, de façon à maintenir la cohérence entre deux parties du modèle. Vous pouvez également écrire une règle qui empêche une modification non valide en annulant la transaction.

Pour plus d'informations sur les transactions, consultez Comment : lier des mises à jour de modèles à l'aide de transactions.

Définition de gestionnaires d'événements

Pour qu'un gestionnaire d'événements soit appelé lorsqu'une modification se produit, vous devez enregistrer celui-ci. Vous devez enregistrer le gestionnaire pour chaque classe d'élément que vous voulez surveiller, comme UseCase ou Activity. Vous n'avez pas besoin de l'enregistrer pour chaque instance.

L'exemple qui suit définit la couleur d'une classe UML d'après le stéréotype que l'utilisateur applique. Les gestionnaires d'événements sont enregistrés pour être déclenchés chaque fois qu'une instance de stéréotype est créée ou supprimée. Dans la mesure où cet exemple utilise des gestionnaires d'événements et non des règles, les gestionnaires sont appelés après l'achèvement de la transaction dans laquelle le stéréotype est modifié. Étant donné que la couleur est également une modification dans le Magasin VMSDK, celle-ci doit être exécutée dans une deuxième transaction.

Vous pouvez également utiliser des gestionnaires d'événements pour exécuter des modifications à l'extérieur du Magasin.

Vous pouvez adapter le code de l'exemple suivant pour répondre aux événements de votre choix. Les points importants à noter à propos de ce code sont les suivants :

  • L'API de validation est utilisée pour enregistrer les gestionnaires d'événements. L'infrastructure de validation offre un moyen pratique d'exécuter le code lorsque le modèle est ouvert. Toutefois, le code n'exécute pas réellement la validation et l'utilisateur n'a pas besoin d'appeler la validation pour effectuer des mises à jour.

  • Les gestionnaires d'événements sont des méthodes qui sont ajoutées à Store.EventManagerDirectory. Il s'agit du Store de l'implémentation VMSDK (DSL) sous-jacente, et non du ModelStore UML. EventManagerDirectory a un ensemble fixe de dictionnaires pour les différents types d'événements, tels que ElementAdded et ElementDeleted.

  • Pour enregistrer un événement, vous devez connaître le nom de la classe d'implémentation ou de la relation que vous voulez surveiller. Ces classes sont définies dans Microsoft.VisualStudio.Modeling.Uml.dll, et vous pouvez voir leurs noms lorsque vous consultez les propriétés dans le débogueur. Vous pouvez effectuer le cast de ces membres de classe en types d'interface appropriés tels que IClass ou IStereotype. Pour obtenir la liste des types d'interfaces, consultez Types d'éléments de modèles.

    Les noms de classe d'implémentation peuvent être différents dans les versions ultérieures.

  • Les gestionnaires d'événements sont appelés lorsque l'utilisateur appelle les commandes Undo et Redo. Par exemple, après un événement Add, la commande Undo déclenche un événement Delete. Votre gestionnaire d'événements doit répondre à ces événements s'il propage des modifications à l'extérieur du Magasin. En revanche, il ne doit pas effectuer de modifications à l'intérieur du Magasin en réponse aux commandes Undo ou Redo, et ne doit pas réaliser des modifications lorsque le modèle est lu à partir du fichier. Vous pouvez utiliser if (!store.InUndoRedoOrRollback && !store.InSerializationTransaction)....

  • L'exemple montre des gestionnaires d'événements pour l'ajout et la suppression d'objets dans le modèle. Vous pouvez également créer des gestionnaires d'événements pour les modifications dans les valeurs de propriété. Pour plus d'informations, consultez Propagation de modifications en dehors du modèle par des gestionnaires d'événements.

  • Pour plus d'informations sur les événements, consultez Propagation de modifications en dehors du modèle par des gestionnaires d'événements.

Exemple : Coloration de classes avec des stéréotypes à l'aide d'événements

Pour cet exemple, vous devez également ajouter une référence de projet à System.Drawing.dll

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.Linq;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.Profiles;
using Microsoft.VisualStudio.Uml.UseCases;

using Microsoft.VisualStudio.Uml.ModelStore; // in private assembly. Used for Get|IsElementDefinition()

namespace UmlEvents  // <<<< EDIT
{
/// <summary>
/// Wraps a UML model to add stereotype coloring.
/// </summary>
public partial class ColoringModelAdapter
{
  // This is the underlying DSL store, not the wrapping UML ModelStore:
  private Store store;

  /// <summary>
  /// This isn't actually validation. It's to couple this adapter to the model before we start.
  /// The validation package creates an instance of this class and then calls this method.
  /// See "Validation": https://msdn.microsoft.com/library/bb126413.aspx
  /// </summary>
  /// <param name="vcontext"></param>
  /// <param name="model"></param>
  [Export(typeof(System.Action<ValidationContext, object>))]
  [ValidationMethod(ValidationCategories.Open)]
  public void ConnectAdapterToModel(ValidationContext vcontext, IModel model)
  {
    // This is the underlying DSL store, not the wrapping UML ModelStore:
    store = (model as ModelElement).Store;

    // Add an event that triggers on creating a stereotype instance.
    // See "Event handlers": https://msdn.microsoft.com/library/bb126250.aspx
    DomainClassInfo siClass = store.DomainDataDirectory.FindDomainClass
      ("Microsoft.VisualStudio.Uml.Classes.StereotypeInstance");
    store.EventManagerDirectory.ElementAdded.Add(siClass,
      new EventHandler<ElementAddedEventArgs>(StereotypeInstanceAdded));

    // For the deletion, we need to trigger from the deleted link
    // between the stereotype instance and the model element - 
    // because after deletion we can't find the element from the stereotype instance.
    DomainRelationshipInfo linkToStereotypeClass = store.DomainDataDirectory.FindDomainRelationship
      ("Microsoft.VisualStudio.Uml.Classes.ElementHasAppliedStereotypeInstances");
    store.EventManagerDirectory.ElementDeleted.Add(linkToStereotypeClass,
      new EventHandler<ElementDeletedEventArgs>(StereotypeInstanceDeleted));

    // Add here handlers for other events.
  }

  /// <summary>
  /// Event handler called whenever a stereotype instance is linked to a uml model element.
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void StereotypeInstanceAdded(object sender, ElementAddedEventArgs e)
  {
    // Don't handle changes in undo or load from file:
    if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;

    IStereotypeInstance si = e.ModelElement as IStereotypeInstance;
    IElement umlElement = si.Element;

     // Work only with the core model, not the views:
     if (!umlElement.IsElementDefinition()) return;

    // I'm only interested in coloring classes and interfaces:
    if (!(umlElement is IType)) return;

    Color? color = ColorForStereotype(si.Name);
    if (color.HasValue)
    {
      SetColorOfShapes(si.Element, color.Value);
    }
  }

  /// <summary>
  /// Called whenever a stereotype instance is deleted - well, actually, 
  /// when the link between the stereotype instance and the uml model element is deleted.
  /// Triggering on the link deletion allows us to get both ends.
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void StereotypeInstanceDeleted(object sender, ElementDeletedEventArgs e)
  {
    // Don't handle changes in undo or load from file:
    if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;

    // Use the generic link type to avoid unearthing the UML implementation DLL:
    ElementLink elementToStereotypeLink = e.ModelElement as ElementLink;
    IElement umlElement = elementToStereotypeLink.LinkedElements[0] as IElement;
    IStereotypeInstance si = elementToStereotypeLink.LinkedElements[1] as IStereotypeInstance;

     // Work only with the core model, not the views:
     if (!umlElement.IsElementDefinition()) return;

    // We're here either because a stereotype is being un-applied,
    // or because the uml element is being deleted.
    // Don't bother if the element is being deleted:
    if ((umlElement as ModelElement).IsDeleting) return;

    // We're only interested in classes and interfaces:
    if (!(umlElement is IType)) return;

    // Because more than one stereotype can be applied to an element,
    // we should check to see if there are any remaining:
    Color newColor = Color.WhiteSmoke; // Default if there aren't.
    foreach (IStereotypeInstance remainingSi in umlElement.AppliedStereotypes)
    {
      Color? color = ColorForStereotype(remainingSi.Name);
      if (color.HasValue)
      {
        newColor = color.Value;
        break;
      }
    }
    SetColorOfShapes(umlElement, newColor);
  }

  private void SetColorOfShapes(IElement element, Color color)
  {
    foreach (IShape shape in element.Shapes())
    {
      shape.Color = color;
    }
  }

  /// <summary>
  /// This example deals only with a subset of the standard stereotypes.
  /// </summary>
  private Color? ColorForStereotype(string name)
  {
    switch (name)
    {
      case "focus": return Color.AliceBlue;
      case "auxiliary": return Color.Bisque;
      case "specification": return Color.OliveDrab;
      case "realization": return Color.LightSeaGreen;
      case "implementationClass": return Color.PaleGoldenrod;
    }
    return null;
  } 
}}

Définition de règles

Vous pouvez définir une règle pour propager une modification dans le Magasin VMSDK. La modification de déclenchement et la règle sont exécutées dans la même transaction. Lorsque l'utilisateur appelle la commande Undo, les deux modifications sont annulées ensemble.

L'exemple précédent a pour inconvénient d'utiliser des gestionnaires d'événements afin de modifier la couleur des formes. La couleur étant aussi associée à un champ dans le Magasin VMSDK, elle doit être exécuté dans une transaction. Par conséquent, si l'utilisateur appelle la commande Undo après avoir appliqué un stéréotype, la modification de couleur est annulée, mais le stéréotype est toujours appliqué. Une autre commande Undo est nécessaire pour inverser l'application du stéréotype. Parfois, l'effet produit peut être celui que vous attendiez, mais si ce n'est pas le cas, vous pouvez propager les modifications dans une transaction en définissant des règles.

Les règles sont moins utiles pour propager des modifications à l'extérieur du magasin, car elles ne sont pas appelées lorsque l'utilisateur exécute une commande Undo ou Redo.

Une règle est une classe enregistrée avec le gestionnaire de règles. Normalement, lorsque vous écrivez du code VMSDK, vous enregistrez une règle en associant un attribut à la classe et en incluant la classe dans une liste lue lorsque le code d'extension est chargé. Toutefois, comme l'implémentation UML est déjà compilée, vous devez ajouter dynamiquement la règle au gestionnaire de règles. Le code fourni dans l'exemple dépend fortement de la gestion des règles d'implémentation en cours, qui peut changer dans les versions ultérieures.

Pour ajouter une règle, vous devez connaître les noms des classes d'implémentation. Ceux-ci peuvent changer dans les versions ultérieures. Vous devez autant que possible effectuer le cast des éléments en types d'API UML tels que IClass ou IProfile.

L'exemple indique des règles qui gèrent l'ajout et la suppression d'objets dans le modèle UML. Vous pouvez également créer des règles qui répondent aux modifications dans les propriétés des objets. Pour plus d'informations, consultez Propagation de modifications dans le modèle par des règles.

Exemple : Coloration de classes avec des stéréotypes à l'aide de règles

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.UseCases; 

using Microsoft.VisualStudio.Uml.ModelStore; // in private assembly. Used for Get|IsElementDefinition()


namespace UmlRules
{
  class ColorByStereotype
  {
    /// <summary>
    /// Singleton wrappers: one per model.
    /// </summary>
    private static Dictionary<IPackage, ColorByStereotype > modelAdapters = 
        new Dictionary<IPackage, ColorByStereotype >();

    private class Wrapper
    {
      /// <summary>
      /// This isn't actually validation. 
      /// It sets up some store rules.
      /// The validation package creates an instance of this class and then calls this method.
      /// See "Validation": https://msdn.microsoft.com/library/bb126413.aspx
      /// </summary>
      /// <param name="vcontext"></param>
      /// <param name="model"></param>
      [Export(typeof(System.Action<ValidationContext, object>))]
      [ValidationMethod(ValidationCategories.Open)]
      private void ConnectAdapterToModel(ValidationContext vcontext, IModel model)
      {
        modelAdapters.Add(model, new ColorByStereotype (model));
      }
    }

    private IModel model;
    private Store store;
    private ColorByStereotype (IModel model)
    {
      this.model = model;
      // This is the underlying DSL store, not the wrapping UML ModelStore:
      store = (model as ModelElement).Store;

      SetRule<StereotypeInstanceAddedRule>(
        store.DomainDataDirectory.FindDomainClass(
          "Microsoft.VisualStudio.Uml.Classes.StereotypeInstance"));
      
      // For the deletion, we need to trigger from the deleted link
      // between the stereotype instance and the model element - 
      // because after deletion we can't find the element from the stereotype instance.
      
      SetRule<StereotypeInstanceDeletedRule>(
        store.DomainDataDirectory.FindDomainRelationship(
        "Microsoft.VisualStudio.Uml.Classes.ElementHasAppliedStereotypeInstances"));
    }

    /// <summary>
    /// Register a rule. 
    /// Normally, you set a rule by prefixing the rule class with 
    /// [RuleOn(typeof(TargetClass))]
    /// but we are setting up the rule at runtime, so must add
    /// the rules to the relevant dictionaries.
    /// </summary>
    /// <typeparam name="T">Rule class</typeparam>
    /// <param name="classInfo">Class or relationship to which to attach the rule.</param>
    private void SetRule<T>(DomainClassInfo classInfo) where T : Rule, new()
    {
      T rule = new T();
      rule.FireTime = TimeToFire.TopLevelCommit;

      System.Type tt = typeof(T);
      string ruleSet = (typeof(AddRule).IsAssignableFrom(tt)) ? "AddRules" :
        (typeof(ChangeRule).IsAssignableFrom(tt)) ? "ChangeRules" :
        (typeof(DeleteRule).IsAssignableFrom(tt)) ? "DeleteRules" :
        (typeof(DeletingRule).IsAssignableFrom(tt)) ? "DeletingRules" : "";

      // The rest of this method uses reflection to achieve the following:
      // store.RuleManager.RegisterRule(rule);
      // classInfo.AddRules.Add(rule);

      System.Reflection.BindingFlags privateBinding = 
          System.Reflection.BindingFlags.Instance 
        | System.Reflection.BindingFlags.NonPublic;
      System.Reflection.MethodInfo mi = 
        typeof(RuleManager).GetMethod("RegisterRule", privateBinding);
      mi.Invoke(store.RuleManager, new object[] { rule });

      store.RuleManager.EnableRule(typeof(T));

      System.Reflection.PropertyInfo pi = 
        typeof(DomainClassInfo).GetProperty(ruleSet, privateBinding);
      dynamic rules = pi.GetValue(classInfo, null);
      System.Type ruleListType = rules.GetType();
      System.Reflection.FieldInfo listpi = 
        ruleListType.GetField("list", privateBinding);
      dynamic list = listpi.GetValue(rules);
      System.Type listType = list.GetType();
      System.Reflection.MethodInfo addmi = listType.GetMethod("Add");
      addmi.Invoke(list, new object[] { rule });


      System.Reflection.MethodInfo resetRulesCache = 
        typeof(DomainClassInfo).GetMethod("ResetRulesCache", privateBinding);
      resetRulesCache.Invoke(classInfo, null);

    }

    #region Rules.
    private class StereotypeInstanceAddedRule : AddRule
    {
      public override void ElementAdded(ElementAddedEventArgs e)
      {
        base.ElementAdded(e);
        Store store = e.ModelElement.Store;
        // Don't handle load from file:
        if (store.InSerializationTransaction)
          return;

        IStereotypeInstance si = e.ModelElement as IStereotypeInstance;
        IElement umlElement = si.Element;
        
         // Work only with the core model, not the views:
         if (!umlElement.IsElementDefinition()) return;

        // I'm only interested in coloring classes and interfaces:
        if (!(umlElement is IType)) return;

        Color? color = ColorForStereotype(si.Name);
        if (color.HasValue)
        {
          SetColorOfShapes(si.Element, color.Value);
        }
      }
    }
    private class StereotypeInstanceDeletedRule : DeleteRule
    {
      public override void ElementDeleted(ElementDeletedEventArgs e)
      {
        base.ElementDeleted(e);
        Store store = e.ModelElement.Store;


        // Use the generic link type to avoid using the UML implementation DLL:
        ElementLink elementToStereotypeLink = e.ModelElement as ElementLink;
        IElement umlElement = elementToStereotypeLink.LinkedElements[0] as IElement;

         // Work only with the core model, not the views:
         if (!umlElement.IsElementDefinition()) return;

        // We're here either because a stereotype is being un-applied,
        // or because the uml element is being deleted.
        // Don't bother if the element is being deleted:
        if ((umlElement as ModelElement).IsDeleting) return;

        // We're only interested in classes and interfaces:
        if (!(umlElement is IType)) return;

        // Because more than one stereotype can be applied to an element,
        // we should check to see if there are any remaining:
        Color newColor = Color.WhiteSmoke; // Default if there aren't.
        foreach (IStereotypeInstance remainingSi in umlElement.AppliedStereotypes)
        {
          Color? color = ColorForStereotype(remainingSi.Name);
          if (color.HasValue)
          {
            newColor = color.Value;
            break;
          }
        }
        SetColorOfShapes(umlElement, newColor);
      }
    }

    /// <summary>
    /// Set the color of the shapes that display an element.
    /// </summary>
    /// <param name="element"></param>
    /// <param name="color"></param>
    private static void SetColorOfShapes(IElement element, Color color)
    {
      foreach (IShape shape in element.Shapes())
      {
        shape.Color = color;
      }
    }

    /// <summary>
    /// For this sample, we just deal with some of the standard stereotypes.
    /// </summary>
    /// <param name="name">Stereotype name</param>
    /// <returns></returns>
    private static Color? ColorForStereotype(string name)
    {
      switch (name)
      {
        case "focus": return Color.AliceBlue;
        case "auxiliary": return Color.Bisque;
        case "specification": return Color.OliveDrab;
        case "realization": return Color.LightSeaGreen;
        case "implementationClass": return Color.PaleGoldenrod;
      }
      return null;
    }
    #endregion
  }
}

Exemple : Associations bidirectionnelles par défaut

Par défaut, lorsque vous dessinez une association dans un diagramme de classes, la nouvelle association est navigable dans une seule direction. Elle possède une flèche à l'une de ses extrémités. Dans certains cas, il est plus pratique de dessiner des associations bidirectionnelles sans flèche. Vous pouvez faire des associations bidirectionnelles la valeur par défaut en ajoutant la règle suivante.

/// <summary>
/// Rule invoked when an Association is created.
/// This rule sets both ends navigable, which is convenient for representing requirements.
/// </summary>
private class AssociationAddRule : AddRule
{
  public override void ElementAdded(ElementAddedEventArgs e)
  {
    Store store = e.ModelElement.Store;
    IAssociation association = e.ModelElement as IAssociation;

    // Do not apply the rule if we are reading from file or undoing a deletion:
    if (association.MemberEnds.Count() == 0 
       || store.InSerializationTransaction || store.InUndoRedoOrRollback) return;

    // Do not apply the rule unless a containing package or model has imported 
    // a profile that defines the stereotype "Default Binary Associations" for associations:
    // if (!association.ApplicableStereotypes.Any
    //      (s => s.DisplayName == "Default Binary Associations")) return;

    // Don’t apply the rule to use cases:
    if (!(association.SourceElement is IUseCase && association.TargetElement is IUseCase))
    {
      association.OwnedEnds.First().SetNavigable(true);
      association.OwnedEnds.Last().SetNavigable(true);
    }
  }
}

Pour enregistrer la règle, vous devez utiliser la méthode SetRule décrite dans Définition de règles :

SetRule<AssociationAddRule>(store.DomainDataDirectory.
      FindDomainRelationship("Microsoft.VisualStudio.Uml.Classes.Association"));

Si vous souhaitez être en mesure d'activer ou de désactiver cette règle, une méthode possible consiste à définir un profil dans lequel un stéréotype particulier est défini. Vous pouvez ajouter du code à votre règle pour vérifier que le profil a été activé dans un package contenant ou un modèle. Pour plus d'informations, consultez Comment : définir un profil pour étendre UML.

Modèle de noyau et modèle Vue

Le modèle UML se compose de plusieurs modèles VMSDK (DSL) :

  • Le modèle de noyau contient des représentations de tous les éléments dans le modèle UML. L'utilisateur peut afficher ces éléments dans la fenêtre Explorateur de modèles UML, et vous pouvez y accéder via l'API ModelStore UML. Le modèle de noyau occupe une partition du Magasin VMSDK.

  • Il existe un modèle Vue pour chaque diagramme UML dans le projet UML. Les objets dans chaque modèle Vue sont des proxys pour les objets dans le modèle de noyau. Il existe un objet de modèle Vue pour chaque élément affiché dans le diagramme UML. Chaque modèle Vue occupe une partition du Magasin VMSDK.

  • Il existe un objet de forme VMSDK pour chaque élément affiché dans un diagramme. La relation entre les formes et les éléments de modèle Vue est de 1:1.

Lorsque vous définissez des gestionnaires d'événements ou de règles, ils sont appelés en cas de modification des objets principaux et de vue. Vous devez gérer uniquement les modifications apportées aux objets principaux. Les gestionnaires dans les exemples utilisent element.IsElementDefinition() pour déterminer s'ils traitent l'objet principal.

Pour utiliser cette méthode, vous devez ajouter une référence de projet à :

%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Uml.dll

Avertissement

IsElementDefinition et d'autres méthodes définies dans l'assembly privé pourraient changer dans les versions ultérieures.

using Microsoft.VisualStudio.Uml.ModelStore; 
  // in private assembly. Used for GetElementDefinition()
...
  // Determine whether an element is view or core:
  if (anElement.IsElementDefinition()) 
  { /* core */ }
  else
  { /* view */ }
...
  // If shapeElement is a shape on a diagram -
  // The VMSDK element connected to the shape is in the view:
  IElement viewModelElement = shapeElement.ModelElement as IElement;
  // Get the core element for which the view is a proxy:
  IElement coreModelElement = viewModelElement.GetElementDefinition();
...

Voir aussi

Tâches

Propagation de modifications en dehors du modèle par des gestionnaires d'événements

Autres ressources

Comment : naviguer dans le modèle UML

Exemple : application d'une couleur par stéréotype (page éventuellement en anglais)

Historique des modifications

Date

Historique

Motif

Mars 2011

Rubrique créée.

Commentaires client.