Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Als Autor einer domänenspezifischen Sprache (DSL) können Sie Validierungseinschränkungen definieren, um zu überprüfen, ob das vom Benutzer erstellte Modell aussagekräftig ist. Wenn Ihr DSL es Benutzern beispielsweise ermöglicht, einen Familienbaum von Personen und ihren Vorfahren zu zeichnen, könnten Sie eine Einschränkung schreiben, die sicherstellt, dass Kinder Geburtsdaten nach ihren Eltern haben.
Sie können die Gültigkeitsprüfungseinschränkungen ausführen, wenn das Modell gespeichert wird, wenn es geöffnet wird, und wenn der Benutzer explizit den Menübefehl "Überprüfen" ausführt. Sie können die Überprüfung auch unter Programmsteuerung ausführen. Beispielsweise können Sie die Überprüfung als Reaktion auf eine Änderung eines Eigenschaftswerts oder einer Beziehung ausführen.
Die Validierung ist besonders wichtig, wenn Sie Textvorlagen oder andere Tools schreiben, die die Modelle Ihrer Benutzer verarbeiten. Die Validierung stellt sicher, dass die Modelle die von diesen Tools angenommenen Voraussetzungen erfüllen.
Warnung
Sie können auch zulassen, dass Validierungseinschränkungen in separaten Erweiterungen für Ihr DSL definiert werden, sowie Erweiterungsmenübefehle und Gestikhandler. Benutzer können diese Erweiterungen zusätzlich zu Ihrem DSL installieren. Weitere Informationen finden Sie unter Erweitern Ihres DSL mithilfe von MEF.
Ausführen der Überprüfung
Wenn ein Benutzer ein Modell bearbeitet, d. a. eine Instanz Ihrer domänenspezifischen Sprache, können die folgenden Aktionen die Überprüfung ausführen:
Klicken Sie mit der rechten Maustaste auf das Diagramm, und wählen Sie "Alle überprüfen" aus.
Klicken Sie im Explorer Ihres DSL mit der rechten Maustaste auf den oberen Knoten, und wählen Sie "Alle überprüfen" aus.
Speichern Sie das Modell.
Öffnen Sie das Modell.
Darüber hinaus können Sie Programmcode schreiben, der die Überprüfung ausführt, z. B. als Teil eines Menübefehls oder als Reaktion auf eine Änderung.
Alle Überprüfungsfehler werden im Fenster " Fehlerliste " angezeigt. Der Benutzer kann auf eine Fehlermeldung doppelklicken, um die Modellelemente auszuwählen, die die Ursache des Fehlers sind.
Definieren von Gültigkeitseinschränkungen
Sie definieren Validierungseinschränkungen, indem Sie den Domänenklassen oder Beziehungen Ihres DSL Validierungsmethoden hinzufügen. Wenn die Überprüfung entweder vom Benutzer oder unter Programmsteuerung ausgeführt wird, werden einige oder alle Überprüfungsmethoden ausgeführt. Jede Methode wird auf jede Instanz ihrer Klasse angewendet, und es können mehrere Überprüfungsmethoden in jeder Klasse vorhanden sein.
Jede Überprüfungsmethode meldet alle gefundenen Fehler.
Hinweis
Überprüfungsmethoden melden Fehler, ändern jedoch nicht das Modell. Wenn Sie bestimmte Änderungen anpassen oder verhindern möchten, lesen Sie Alternativen zur Überprüfung.
So definieren Sie eine Gültigkeitsprüfungseinschränkung
Aktivieren sie die Überprüfung im Knoten "Editor\Validierung ":
Öffnen Sie Dsl\DslDefinition.dsl.
Erweitern Sie im DSL-Explorer den Knoten "Editor ", und wählen Sie "Validierung" aus.
Legen Sie im Eigenschaftenfenster die Eigenschaften auf " Verwendet " fest
true. Es ist am praktischsten, alle diese Eigenschaften festzulegen.Klicken Sie auf der Symbolleiste des Projektmappen-Explorers auf "Alle Vorlagen transformieren".
Schreiben Sie partielle Klassendefinitionen für eine oder mehrere Ihrer Domänenklassen oder Domänenbeziehungen. Schreiben Sie diese Definitionen in eine neue Codedatei im Dsl-Projekt .
Präfix jeder Klasse mit diesem Attribut:
[ValidationState(ValidationState.Enabled)]- Standardmäßig aktiviert dieses Attribut auch die Überprüfung für abgeleitete Klassen. Wenn Sie die Überprüfung für eine bestimmte abgeleitete Klasse deaktivieren möchten, können Sie dies verwenden
ValidationState.Disabled.
- Standardmäßig aktiviert dieses Attribut auch die Überprüfung für abgeleitete Klassen. Wenn Sie die Überprüfung für eine bestimmte abgeleitete Klasse deaktivieren möchten, können Sie dies verwenden
Fügen Sie den Klassen Validierungsmethoden hinzu. Jede Überprüfungsmethode kann einen beliebigen Namen haben, aber einen Parameter vom Typ ValidationContexthaben.
Sie muss einem oder
ValidationMethodmehreren Attributen vorangestellt werden:[ValidationMethod (ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu ) ]Die ValidationCategories geben an, wann die Methode ausgeführt wird.
Beispiel:
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Validation;
// Allow validation methods in this class:
[ValidationState(ValidationState.Enabled)]
// In this DSL, ParentsHaveChildren is a domain relationship
// from Person to Person:
public partial class ParentsHaveChildren
{
// Identify the method as a validation method:
[ValidationMethod
( // Specify which events cause the method to be invoked:
ValidationCategories.Open // On file load.
| ValidationCategories.Save // On save to file.
| ValidationCategories.Menu // On user menu command.
)]
// This method is applied to each instance of the
// type (and its subtypes) in a model:
private void ValidateParentBirth(ValidationContext context)
{
// In this DSL, the role names of this relationship
// are "Child" and "Parent":
if (this.Child.BirthYear < this.Parent.BirthYear
// Allow user to leave the year unset:
&& this.Child.BirthYear != 0)
{
context.LogError(
// Description:
"Child must be born after Parent",
// Unique code for this error:
"FAB001ParentBirthError",
// Objects to select when user double-clicks error:
this.Child,
this.Parent);
}
}
Beachten Sie die folgenden Punkte zu diesem Code:
Sie können Überprüfungsmethoden zu Domänenklassen oder Domänenbeziehungen hinzufügen. Der Code für diese Typen befindet sich in Dsl\Generated Code\Domain*.cs.
Jede Überprüfungsmethode wird auf jede Instanz ihrer Klasse und deren Unterklassen angewendet. Bei einer Domänenbeziehung ist jede Instanz eine Verknüpfung zwischen zwei Modellelementen.
Validierungsmethoden werden nicht in einer bestimmten Reihenfolge angewendet, und jede Methode wird nicht auf die Instanzen der Klasse in einer vorhersehbaren Reihenfolge angewendet.
Es ist in der Regel schlechte Praxis für eine Validierungsmethode, den Speicherinhalt zu aktualisieren, da dies zu inkonsistenten Ergebnissen führen würde. Stattdessen sollte die Methode einen beliebigen Fehler durch Aufrufen von
context.LogError,LogWarningoderLogInfomelden.Im LogError-Aufruf können Sie eine Liste der Modellelemente oder Beziehungslinks bereitstellen, die ausgewählt werden, wenn der Benutzer auf die Fehlermeldung doppelkligt.
Informationen zum Lesen des Modells im Programmcode finden Sie unter Navigieren und Aktualisieren eines Modells im Programmcode.
Das Beispiel gilt für das folgende Domänenmodell. Die "ParentsHaveChildren"-Beziehung hat Rollen mit den Namen "Kind" und "Elternteil".
Gültigkeitsprüfungskategorien
ValidationMethodAttribute Im Attribut geben Sie an, wann die Validierungsmethode ausgeführt werden soll.
| Kategorie | Ausführung |
|---|---|
| ValidationCategories | Wenn der Benutzer den Menübefehl "Überprüfen" aufruft. |
| ValidationCategories | Wenn die Modelldatei geöffnet wird. |
| ValidationCategories | Wenn die Datei gespeichert wird. Wenn Überprüfungsfehler auftreten, erhält der Benutzer die Möglichkeit, den Speichervorgang abzubrechen. |
| ValidationCategories | Wenn die Datei gespeichert wird. Wenn in dieser Kategorie Fehler von Methoden auftreten, wird der Benutzer gewarnt, dass es möglicherweise nicht möglich ist, die Datei erneut zu öffnen. Verwenden Sie diese Kategorie für Überprüfungsmethoden, die auf duplizierte Namen oder IDs oder andere Bedingungen testen, die zu Ladefehlern führen können. |
| ValidationCategories | Wenn die ValidateCustom-Methode aufgerufen wird. Validierungen in dieser Kategorie können nur über Programmcode aufgerufen werden. Weitere Informationen finden Sie unter "Benutzerdefinierte Überprüfungskategorien". |
Speicherort für Validierungsmethoden
Sie können häufig denselben Effekt erzielen, indem Sie eine Validierungsmethode auf einen anderen Typ setzen. Sie könnten beispielsweise eine Methode zur Person-Klasse hinzufügen, anstatt die ElternHaveChildren-Beziehung zu nutzen, und diese Methode dann die Links durchlaufen lassen.
[ValidationState(ValidationState.Enabled)]
public partial class Person
{[ValidationMethod
( ValidationCategories.Open
| ValidationCategories.Save
| ValidationCategories.Menu
)
]
private void ValidateParentBirth(ValidationContext context)
{
// Iterate through ParentHasChildren links:
foreach (Person parent in this.Parents)
{
if (this.BirthYear <= parent.BirthYear)
{ ...
Aggregieren von Gültigkeitseinschränkungen. Um die Validierung in einer vorhersagbaren Reihenfolge anzuwenden, definieren Sie eine einzelne Überprüfungsmethode für eine Besitzerklasse, z. B. das Stammelement Ihres Modells. Mit dieser Technik können Sie auch mehrere Fehlerberichte in einer einzelnen Nachricht aggregieren.
Nachteile sind, dass die kombinierte Methode weniger einfach zu verwalten ist und dass die Einschränkungen alle dieselben ValidationCategorieshaben müssen. Daher wird empfohlen, jede Einschränkung bei Bedarf in einer separaten Methode beizubehalten.
Übergeben von Werten im Kontextcache. Der Kontextparameter verfügt über ein Wörterbuch, in das Sie beliebige Werte platzieren können. Das Wörterbuch wird für die Lebensdauer der Überprüfungsausführung beibehalten. Eine bestimmte Überprüfungsmethode kann z. B. eine Fehleranzahl im Kontext beibehalten und verwenden, um zu vermeiden, dass das Fehlerfenster mit wiederholten Meldungen überflutet wird. Beispiel:
List<ParentsHaveChildren> erroneousLinks;
if (!context.TryGetCacheValue("erroneousLinks", out erroneousLinks))
erroneousLinks = new List<ParentsHaveChildren>();
erroneousLinks.Add(this);
context.SetCacheValue("erroneousLinks", erroneousLinks);
if (erroneousLinks.Count < 5) { context.LogError( ... ); }
Validierung von Multiplicitäten
Validierungsmethoden für die Überprüfung der minimalen Multiplikation werden automatisch für Ihr DSL generiert. Der Code wird in Dsl\Generated Code\MultiplicityValidation.cs geschrieben. Diese Methoden werden wirksam, wenn Sie die Überprüfung im Editor\Validation-Knoten im DSL-Explorer aktivieren.
Wenn Sie die Multiplikation einer Rolle einer Domänenbeziehung auf 1...* oder 1..1 festlegen, aber der Benutzer keine Verknüpfung dieser Beziehung erstellt, wird eine Überprüfungsfehlermeldung angezeigt.
Wenn Ihr DSL beispielsweise Über Klassen Person und Town verfügt und eine Beziehung PersonLivesInTown mit einer Beziehung 1..\* in der Rolle "Stadt" hat, wird für jede Person, die keine Stadt hat, eine Fehlermeldung angezeigt.
Ausführen der Überprüfung vom Programmcode aus
Sie können die Überprüfung ausführen, indem Sie auf einen ValidationController zugreifen oder einen ValidationController erstellen. Wenn die Fehler dem Benutzer im Fehlerfenster angezeigt werden sollen, verwenden Sie den ValidationController, der an das DocData-Objekt des Diagramms angefügt ist. Wenn Sie beispielsweise einen Menübefehl schreiben, steht CurrentDocData.ValidationController in der Klasse mit dem Befehlssatz zur Verfügung.
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Modeling.Shell;
...
partial class MyLanguageCommandSet
{
private void OnMenuMyContextMenuCommand(object sender, EventArgs e)
{
ValidationController controller = this.CurrentDocData.ValidationController;
...
Weitere Informationen finden Sie unter So fügen Sie einen Befehl zum Kontextmenü hinzu.
Sie können auch einen separaten Überprüfungscontroller erstellen und die Fehler selbst verwalten. Beispiel:
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Modeling.Shell;
...
Store store = ...;
VsValidationController validator = new VsValidationController(s);
// Validate all elements in the Store:
if (!validator.Validate(store, ValidationCategories.Save))
{
// Deal with errors:
foreach (ValidationMessage message in validator.ValidationMessages) { ... }
}
Ausführen der Überprüfung, wenn eine Änderung auftritt
Wenn Sie sicherstellen möchten, dass der Benutzer sofort gewarnt wird, wenn das Modell ungültig wird, können Sie ein Speicherereignis definieren, das die Überprüfung ausführt. Weitere Informationen zu Speicherereignissen finden Sie unter Ereignishandler, die Änderungen außerhalb des Modells weitergeben.
Fügen Sie ihrem DslPackage-Projekt neben dem Validierungscode eine benutzerdefinierte Codedatei hinzu, die dem folgenden Beispiel ähnlich ist. Dieser Code verwendet das ValidationController, das dem Dokument angefügt ist. Dieser Controller zeigt die Überprüfungsfehler in der Visual Studio-Fehlerliste an.
using System;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Validation;
namespace Company.FamilyTree
{
partial class FamilyTreeDocData // Change name to your DocData.
{
// Register the store event handler:
protected override void OnDocumentLoaded()
{
base.OnDocumentLoaded();
DomainClassInfo observedLinkInfo = this.Store.DomainDataDirectory
.FindDomainClass(typeof(ParentsHaveChildren));
DomainClassInfo observedClassInfo = this.Store.DomainDataDirectory
.FindDomainClass(typeof(Person));
EventManagerDirectory events = this.Store.EventManagerDirectory;
events.ElementAdded
.Add(observedLinkInfo, new EventHandler<ElementAddedEventArgs>(ParentLinkAddedHandler));
events.ElementDeleted.Add(observedLinkInfo, new EventHandler<ElementDeletedEventArgs>(ParentLinkDeletedHandler));
events.ElementPropertyChanged.Add(observedClassInfo, new EventHandler<ElementPropertyChangedEventArgs>(BirthDateChangedHandler));
}
// Handler will be called after transaction that creates a link:
private void ParentLinkAddedHandler(object sender,
ElementAddedEventArgs e)
{
this.ValidationController.Validate(e.ModelElement,
ValidationCategories.Save);
}
// Called when a link is deleted:
private void ParentLinkDeletedHandler(object sender,
ElementDeletedEventArgs e)
{
// Don't apply validation to a deleted item!
// - Validate store to refresh the error list.
this.ValidationController.Validate(this.Store,
ValidationCategories.Save);
}
// Called when any property of a Person element changes:
private void BirthDateChangedHandler(object sender,
ElementPropertyChangedEventArgs e)
{
Person person = e.ModelElement as Person;
// Not interested in changes in other properties:
if (e.DomainProperty.Id != Person.BirthYearDomainPropertyId)
return;
// Validate all parent links to and from the person:
this.ValidationController.Validate(
ParentsHaveChildren.GetLinksToParents(person)
.Concat(ParentsHaveChildren.GetLinksToChildren(person))
, ValidationCategories.Save);
}
}
}
Die Handler werden auch nach Rückgängig- oder Wiederholen-Vorgängen aufgerufen, die sich auf die Verknüpfungen oder Elemente auswirken.
Benutzerdefinierte Überprüfungskategorien
Zusätzlich zu den Standardüberprüfungskategorien, z. B. Menü und Öffnen, können Sie Ihre eigenen Kategorien definieren. Sie können diese Kategorien aus dem Programmcode aufrufen. Der Benutzer kann sie nicht direkt aufrufen.
Eine typische Verwendung für benutzerdefinierte Kategorien besteht darin, eine Kategorie zu definieren, die prüft, ob das Modell die Voraussetzungen eines bestimmten Tools erfüllt.
Um einer bestimmten Kategorie eine Gültigkeitsprüfungsmethode hinzuzufügen, stellen Sie ihr ein Attribut wie folgt voran:
[ValidationMethod(CustomCategory = "PreconditionsForGeneratePartsList")]
[ValidationMethod(ValidationCategory.Menu)]
private void TestForCircularLinks(ValidationContext context)
{...}
Hinweis
Sie können einer Methode beliebig viele [ValidationMethod()] Attribute voranstellen. Sie können eine Methode sowohl benutzerdefinierten als auch Standardkategorien hinzufügen.
So rufen Sie eine benutzerdefinierte Überprüfung auf:
// Invoke all validation methods in a custom category:
validationController.ValidateCustom
(store, // or a list of model elements
"PreconditionsForGeneratePartsList");
Alternativen zur Überprüfung
Gültigkeitsprüfungseinschränkungen melden Fehler, ändern das Modell jedoch nicht. Wenn Sie stattdessen verhindern möchten, dass das Modell ungültig wird, können Sie andere Techniken verwenden.
Diese Techniken werden jedoch nicht empfohlen. Es ist in der Regel besser, dem Benutzer zu überlassen, wie ein ungültiges Modell korrigiert werden soll.
Passen Sie die Änderung an, um das Modell wieder gültig zu machen. Wenn der Benutzer beispielsweise eine Eigenschaft über dem zulässigen Maximum festlegt, können Sie die Eigenschaft auf den Maximalwert zurücksetzen. Definieren Sie dazu eine Regel. Weitere Informationen finden Sie unter Regeln, die Änderungen innerhalb des Modells weitergeben.
Führen Sie ein Rollback der Transaktion durch, wenn eine ungültige Änderung versucht wird. Sie können auch eine Regel für diesen Zweck definieren, aber in einigen Fällen ist es möglich, einen Eigenschaftshandler OnValueChanging() außer Kraft zu setzen oder eine Methode wie das OnDeleted(). Zurücksetzen einer Transaktion außer Kraft zu setzen, verwenden Sie this.Store.TransactionManager.CurrentTransaction.Rollback(). weitere Informationen unter Domain Property Value Change Handlers.
Warnung
Stellen Sie sicher, dass der Benutzer weiß, dass die Änderung angepasst oder zurückgesetzt wurde. Verwenden Sie beispielsweise System.Windows.Forms.MessageBox.Show("message")..