Freigeben über


Regeln sorgen dafür, dass Änderungen innerhalb des Modells verbreitet werden.

Sie können eine Speicherregel erstellen, um eine Änderung von einem Element in ein anderes im Visualization and Modeling SDK (VMSDK) zu verteilen. Wenn eine Änderung an einem beliebigen Element im Store erfolgt, werden Regeln zur Ausführung angesetzt, normalerweise wenn die äußerste Transaktion abgeschlossen wird. Es gibt verschiedene Arten von Regeln für verschiedene Arten von Ereignissen, z. B. das Hinzufügen eines Elements oder das Löschen. Sie können Regeln an bestimmte Typen von Elementen, Formen oder Diagrammen anfügen. Viele integrierte Features werden durch Regeln definiert: Regeln stellen beispielsweise sicher, dass ein Diagramm aktualisiert wird, wenn sich das Modell ändert. Sie können Ihre domänenspezifische Sprache anpassen, indem Sie eigene Regeln hinzufügen.

Store-Regeln eignen sich besonders für die Weitergabe von Änderungen innerhalb des Speichers – d. h. Änderungen an Modellelementen, Beziehungen, Formen oder Connectors und deren Domäneneigenschaften. Regeln werden nicht ausgeführt, wenn der Benutzer die Befehle "Rückgängig" oder "Wiederholen" aufruft. Stattdessen stellt der Transaktions-Manager sicher, dass die Speicherinhalte in den richtigen Zustand wiederhergestellt werden. Wenn Sie Änderungen an Ressourcen außerhalb des Stores weitergeben möchten, verwenden Sie Store-Ereignisse. Weitere Informationen finden Sie unter Ereignishandler, die Änderungen außerhalb des Modells weitergeben.

Angenommen, Sie möchten angeben, dass jedes Mal, wenn der Benutzer (oder Ihr Code) ein neues Element vom Typ ExampleDomainClass erstellt, ein zusätzliches Element eines anderen Typs in einem anderen Teil des Modells erstellt wird. Sie könnten ein AddRule schreiben und es exampleDomainClass zuordnen. Sie würden Code in einer Regel schreiben, um das zusätzliche Element zu erstellen.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;

namespace ExampleNamespace
{
 // Attribute associates the rule with a domain class:
 [RuleOn(typeof(ExampleDomainClass), FireTime=TimeToFire.TopLevelCommit)]
 // The rule is a class derived from one of the abstract rules:
 class MyAddRule : AddRule
 {
  // Override the abstract method:
  public override void ElementAdded(ElementAddedEventArgs e)
  {
    base.ElementAdded(e);
    ExampleDomainClass element = e.ModelElement;
    Store store = element.Store;
    // Ignore this call if we're currently loading a model:
    if (store.TransactionManager.CurrentTransaction.IsSerializing)
       return;

    // Code here propagates change as required - for example:
      AnotherDomainClass echo = new AnotherDomainClass(element.Partition);
      echo.Name = element.Name;
      echo.Parent = element.Parent;
    }
  }
 // The rule must be registered:
 public partial class ExampleDomainModel
 {
   protected override Type[] GetCustomDomainModelTypes()
   {
     List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
     types.Add(typeof(MyAddRule));
     // If you add more rules, list them here.
     return types.ToArray();
   }
 }
}

Hinweis

Der Code einer Regel sollte den Status nur von Elementen im Store ändern; d. h. die Regel sollte nur Modellelemente, Beziehungen, Formen, Verbinder, Diagramme oder deren Eigenschaften ändern. Wenn Sie Änderungen an Ressourcen außerhalb des Speichers weitergeben möchten, definieren Sie Store-Ereignisse. Weitere Informationen finden Sie unter Ereignishandler, die Änderungen außerhalb des Modells weitergeben.

So definieren Sie eine Regel

  1. Definieren Sie die Regel als Eine Klasse, die dem RuleOn Attribut vorangestellt ist. Das Attribut ordnet die Regel einer Ihrer Domänenklassen, Beziehungen oder Diagrammelemente zu. Die Regel wird auf jede Instanz dieser Klasse angewendet, die abstrahieren kann.

  2. Registrieren Sie die Regel, indem Sie sie dem von Ihrer Domänenmodellklasse zurückgegebenen GetCustomDomainModelTypes() Satz hinzufügen.

  3. Leiten Sie die Regelklasse von einer der abstrakten Rule-Klassen ab, und schreiben Sie den Code der Ausführungsmethode.

    In den folgenden Abschnitten werden diese Schritte ausführlicher beschrieben.

So definieren Sie eine Regel für eine Domänenklasse

  • Definieren Sie in einer benutzerdefinierten Codedatei eine Klasse, und stellen Sie ihr das RuleOnAttribute Attribut voran:

    [RuleOn(typeof(ExampleElement),
         // Usual value - but required, because it is not the default:
         FireTime = TimeToFire.TopLevelCommit)]
    class MyRule ...
    
    
  • Der Betrefftyp im ersten Parameter kann eine Domänenklasse, eine Domänenbeziehung, ein Shape, ein Verbinder oder ein Diagramm sein. In der Regel wenden Sie Regeln auf Domänenklassen und Beziehungen an.

    Dies FireTime ist in der Regel TopLevelCommit. Dadurch wird sichergestellt, dass die Regel nur ausgeführt wird, nachdem alle primären Änderungen der Transaktion vorgenommen wurden. Die Alternativen sind Inline, die die Regel bald nach der Änderung ausführt; und LocalCommit, das die Regel am Ende der aktuellen Transaktion ausführt (dies ist möglicherweise nicht die äußerste). Sie können auch die Priorität einer Regel festlegen, um die Reihenfolge in der Warteschlange zu beeinflussen, aber dies ist eine unzuverlässige Methode zum Erreichen des benötigten Ergebnisses.

  • Sie können eine abstrakte Klasse als Betrefftyp angeben.

  • Die Regel gilt für alle Instanzen der Subject-Klasse.

  • Der Standardwert für FireTime ist "TimeToFire.TopLevelCommit". Dies bewirkt, dass die Regel ausgeführt wird, wenn die äußerste Transaktion committet wird. Eine Alternative ist TimeToFire.Inline. Dies bewirkt, dass die Regel bald nach dem auslösenden Ereignis ausgeführt wird.

Die Regel registrieren

  • Fügen Sie die Regelklasse zu der Liste der Typen hinzu, die von GetCustomDomainModelTypes in Ihrem Domänenmodell zurückgegeben wird.

    public partial class ExampleDomainModel
     {
       protected override Type[] GetCustomDomainModelTypes()
       {
         List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
         types.Add(typeof(MyAddRule));
         // If you add more rules, list them here.
         return types.ToArray();
       }
     }
    
    
  • Wenn Sie nicht sicher sind, ob der Name Ihrer Domänenmodellklasse angegeben ist, suchen Sie in der Datei Dsl\GeneratedCode\DomainModel.cs

  • Schreiben Sie diesen Code in einer benutzerdefinierten Codedatei in Ihrem DSL-Projekt.

So schreiben Sie den Code der Regel

  • Leiten Sie die Regelklasse von einer der folgenden Basisklassen ab:

    Basisklasse Auslöser
    AddRule Ein Element, ein Link oder ein Shape wird hinzugefügt.

    Verwenden Sie dies, um neue Beziehungen zusätzlich zu neuen Elementen zu erkennen.
    ChangeRule Ein Domäneneigenschaftswert wird geändert. Das Methodenargument stellt die alten und neuen Werte bereit.

    Bei Shapes wird diese Regel ausgelöst, wenn sich die integrierte AbsoluteBounds Eigenschaft ändert, wenn das Shape verschoben wird.

    In vielen Fällen ist es praktischer, OnValueChanged oder OnValueChanging im Eigenschaften-Handler zu überschreiben. Diese Methoden werden unmittelbar vor und nach der Änderung aufgerufen. Im Gegensatz dazu wird die Regel normalerweise am Ende der Transaktion ausgeführt. Weitere Informationen finden Sie unter Domain Property Value Change-Handler. Anmerkung: Diese Regel wird nicht ausgelöst, wenn ein Link erstellt oder gelöscht wird. Schreiben Sie stattdessen eine AddRule und eine DeleteRule für die Domänenbeziehung.
    DeletingRule Wird ausgelöst, wenn ein Element oder ein Link gelöscht werden soll. Die Eigenschaft ModelElement.IsDeleting ist bis zum Ende der Transaktion wahr.
    DeleteRule Wird ausgeführt, wenn ein Element oder ein Link gelöscht wurde. Die Regel wird ausgeführt, nachdem alle anderen Regeln ausgeführt wurden, einschließlich der Löschregeln. "ModelElement.IsDeleting" ist "false", und "ModelElement.IsDeleted" ist "true". Um ein späteres Rückgängigmachen zu ermöglichen, wird das Element nicht tatsächlich aus dem Speicher entfernt, sondern nur aus "Store.ElementDirectory".
    MoveRule Ein Element wird von einer Speicherpartition in eine andere verschoben.

    (Beachten Sie, dass dies nicht mit der grafischen Position eines Shapes verknüpft ist.)
    RolePlayerChangeRule Diese Regel gilt nur für Domänenbeziehungen. Der Vorgang wird ausgelöst, wenn Sie ein Modellelement explizit an einem der beiden Enden eines Links zuweisen.
    RolePlayerPositionChangeRule Wird ausgelöst, wenn die Reihenfolge von Verknüpfungen zu oder von einem Element mithilfe der MoveBefore- oder MoveToIndex-Methoden für einen Link geändert wird.
    TransactionBeginningRule Wird ausgeführt, wenn eine Transaktion erstellt wird.
    TransactionCommittingRule Wird ausgeführt, wenn die Transaktion bestätigt werden soll.
    TransactionRollingBackRule Wird ausgeführt, wenn die Transaktion bald zurückgesetzt werden soll.
  • Jede Klasse verfügt über eine Methode, die Sie außer Kraft setzen. Geben Sie override in Ihre Klasse ein, um sie zu entdecken. Der Parameter dieser Methode identifiziert das Element, das geändert wird.

    Beachten Sie die folgenden Punkte zu Regeln:

  1. Der Satz von Änderungen in einer Transaktion kann viele Regeln auslösen. In der Regel werden die Regeln ausgeführt, wenn die äußerste Transaktion abgeschlossen wird. Sie werden in einer nicht angegebenen Reihenfolge ausgeführt.

  2. Eine Regel wird immer innerhalb einer Transaktion ausgeführt. Daher müssen Sie keine neue Transaktion erstellen, um Änderungen vorzunehmen.

  3. Regeln werden nicht ausgeführt, wenn eine Transaktion rückgängig gemacht wird oder wenn die Vorgänge "Rückgängig" oder "Wiederholen" ausgeführt werden. Diese Vorgänge setzen den gesamten Inhalt des Stores auf den vorherigen Zustand zurück. Wenn Ihre Regel daher den Status von elementen außerhalb des Stores ändert, bleibt sie möglicherweise nicht synchron mit dem Store-Inhalt. Um den Zustand außerhalb des Stores zu aktualisieren, ist es besser, Ereignisse zu verwenden. Weitere Informationen finden Sie unter Ereignishandler, die Änderungen außerhalb des Modells weitergeben.

  4. Einige Regeln werden ausgeführt, wenn ein Modell aus der Datei geladen wird. Um zu ermitteln, ob das Laden oder Speichern ausgeführt wird, verwenden Sie store.TransactionManager.CurrentTransaction.IsSerializing.

  5. Wenn der Code Ihrer Regel weitere Regeltrigger erstellt, werden sie am Ende der Auslösenliste hinzugefügt und vor Abschluss der Transaktion ausgeführt. DeletedRules werden nach allen anderen Regeln ausgeführt. Eine Regel kann in einer Transaktion mehrmals ausgeführt werden, einmal für jede Änderung.

  6. Um Informationen an Regeln zu übergeben und von ihnen zu empfangen, können Sie Informationen in der TransactionContext speichern. Dies ist nur ein Wörterbuch, das während der Transaktion verwaltet wird. Sie wird verworfen, wenn die Transaktion endet. Die Ereignisargumente in jeder Regel ermöglichen den Zugriff darauf. Denken Sie daran, dass Regeln nicht in einer vorhersehbaren Reihenfolge ausgeführt werden.

  7. Verwenden Sie Regeln, nachdem Sie andere Alternativen berücksichtigt haben. Wenn Sie beispielsweise eine Eigenschaft aktualisieren möchten, wenn sich ein Wert ändert, sollten Sie eine berechnete Eigenschaft verwenden. Wenn Sie die Größe oder Position eines Shapes einschränken möchten, verwenden Sie eine BoundsRule. Wenn Sie auf eine Änderung in einem Eigenschaftswert reagieren möchten, fügen Sie der Eigenschaft einen OnValueChanged Handler hinzu. Weitere Informationen finden Sie unter Reagieren auf und Weitergeben von Änderungen.

Example

Im folgenden Beispiel wird eine Eigenschaft aktualisiert, wenn eine Domänenbeziehung instanziiert wird, um zwei Elemente zu verknüpfen. Die Regel wird nicht nur ausgelöst, wenn der Benutzer einen Link in einem Diagramm erstellt, sondern auch, wenn programmcode eine Verknüpfung erstellt.

Um dieses Beispiel zu testen, erstellen Sie ein DSL mit der Projektmappenvorlage "Task Flow", und fügen Sie den folgenden Code in eine Datei im Dsl-Projekt ein. Erstellen und führen Sie die Lösung aus, und öffnen Sie die Beispieldatei im Debugging-Projekt. Zeichnen Sie eine Kommentarverbindung zwischen einer Kommentar-Form und einem Flusselement. Der Text im Kommentar ändert sich, um auf das aktuellste Element zu verweisen, mit dem Sie ihn verbunden haben.

In der Praxis würden Sie in der Regel eine DeleteRule für jedes AddRule schreiben.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;

namespace Company.TaskRuleExample
{

  [RuleOn(typeof(CommentReferencesSubjects))]
  public class RoleRule : AddRule
  {

    public override void ElementAdded(ElementAddedEventArgs e)
    {
      base.ElementAdded(e);
      CommentReferencesSubjects link = e.ModelElement as CommentReferencesSubjects;
      Comment comment = link.Comment;
      FlowElement subject = link.Subject;
      Transaction current = link.Store.TransactionManager.CurrentTransaction;
      // Don't want to run when we're just loading from file:
      if (current.IsSerializing) return;
      comment.Text = "Flow has " + subject.FlowTo.Count + " outgoing connections";
    }

  }

  public partial class TaskRuleExampleDomainModel
  {
    protected override Type[] GetCustomDomainModelTypes()
    {
      List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
      types.Add(typeof(RoleRule));
      return types.ToArray();
    }
  }

}