Ověření domény specifické pro jazyk
Jako autor domény specifické pro jazyk (DSL) můžete definovat omezení ověření ověřit smysluplné modelu vytvořené uživatelem.Například váš DSL umožňuje uživatelům kreslit family tree osob a jejich rodičů a prarodičů, nelze zapsat omezení, která zajišťuje data narození po jejich rodiče dětí.
Máte ověřovací omezení spouštění při uložení modelu, když je otevřen a spustí-li uživatel explicitně ověřit příkaz nabídky.Můžete také provést ověření za řízení programu.Mohl například spustit ověřování v reakci na změnu hodnoty vlastnosti nebo vztah.
Ověření je zvláště důležité, pokud píšete text šablony nebo jiné nástroje, které zpracovávají modely uživatelů.Ověřování zajišťuje, že modely splňují předpoklady, předpokládá se, že pomocí těchto nástrojů.
Upozornění |
---|
Můžete také povolit omezení ověření definovaných v samostatné rozšíření vašeho DSL spolu s rozšíření příkazů nabídek a obsluhy gesto.Uživatelé mohou zvolit instalaci těchto rozšíření vedle vašeho DSL.Další informace naleznete v tématu Rozšířit vaše DSL pomocí MEF. |
Ověření systémem
Když uživatel úpravy modelu, instance domény specifické pro jazyk, následující akce lze spustit ověření:
Klepněte na diagram pravým tlačítkem myši a vyberte Ověřit všechny.
Klepněte pravým tlačítkem myši na horní uzel v aplikaci Explorer DSL a vyberte Ověřit všechny
Uložte model.
Otevřete model.
Kromě toho můžete psát program kód spuštěný ověření, například jako součást příkazu v nabídce nebo v reakci na změnu.
Chyby ověření, se zobrazí v Seznam chyb okna.Uživatele můžete poklepat na chybové zprávy vyberte prvky modelu, které jsou příčinou chyby.
Definování omezení ověření
Ověření omezení definujete přidáním ověřovací metody třídy domény nebo vztahy vaše DSL.Po spuštění ověření uživatele nebo v rámci řízení programu jsou spouštěny některé nebo všechny metody ověřování.Každá metoda se vztahuje na každou instanci své třídy a může být několik metod ověření jednotlivých tříd.
Každá metoda ověření oznámí všechny chyby, které nalezne.
[!POZNÁMKA]
Metody ověření zprávy o chybách, ale neměňte modelu.Pokud chcete upravit nebo zakázat určité změny, viz Alternativy k ověření.
Definovat omezení ověření
Povolit ověření Editor\Validation uzlu:
Otevřete Dsl\DslDefinition.dsl.
V aplikaci Explorer DSL, rozbalte Editor uzlu a vyberte ověření.
V okně vlastnosti nastavena používá vlastnosti a true.Je nejvhodnější nastavení těchto vlastností.
Klepněte na tlačítko Transformace všechny šablony v aplikaci Solution Explorer nástrojů.
Zápis definice částečné třídy pro jeden nebo více tříd domény nebo domény vztahy.Tyto definice zapsat do nového souboru v kódu Dsl projektu.
Každá třída s tímto atributem předpony:
[ValidationState(ValidationState.Enabled)]
- Ve výchozím nastavení tento atribut také povolit ověření pro odvozené třídy.Pokud chcete zakázat ověření pro určité odvozené třídy, můžete použít ValidationState.Disabled.
Přidáte ověřovací metody tříd.Každá metoda ověření mít jakýkoli název může mít jeden parametr typu ValidationContext.
Je nutné zadat s jedním nebo více ValidationMethod atributy:
[ValidationMethod (ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu ) ]
ValidationCategories zadejte provedení metody.
Příklad:
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);
}
}
Oznámení o tomto kódu následující body:
Můžete přidat ověřovací metody třídy domény nebo domény vztahy.Kód pro tyto typy je v Dsl\Generated Code\Domain*.cs.
Každá metoda ověření u každé instanci své třídy a jejích podtříd.Každá instance z vztah domény je propojení mezi dvěma prvky modelu.
V libovolném pořadí určené nejsou použity metody ověření a není použito každou metodu instance třídy v libovolném pořadí předvídatelné.
Protože to by vedlo ke nekonzistentní výsledky je obvykle špatné praxe pro metodu aktualizovat obsah úložiště ověření.Místo toho hlásit všechny chyby voláním metody context.LogError, LogWarning nebo LogInfo.
Volání LogError může poskytnout seznam prvky modelu nebo vztah odkazy, které budou vybrány, když uživatel poklepe chybová zpráva.
Informace o čtení modelu v kódu programu Navigace a aktualizace modelu v kódu programu.
Příklad se vztahuje na následující model domény.ParentsHaveChildren vztah má role, které se nazývají podřízené a nadřazené.
Ověření kategorie
V ValidationMethod atributu, zadejte při metoda ověřování by měly být provedeny.
Kategorie |
Spuštění |
---|---|
Pokud uživatel vyvolá příkaz ověřit. |
|
Při otevření souboru modelu. |
|
Při uložení souboru.Pokud chyby ověření, uživatel bude dána možnost uložit zrušení operace. |
|
Při uložení souboru.Pokud chyby z metod v této kategorii, uživatel bude upozorněn, že nebude možné znovu otevřít soubor. Pomocí této kategorie pro metody ověření, které test pro duplicitní názvy nebo ID nebo jiné podmínky, které mohou způsobit chyby při načítání. |
|
Pokud je volána metoda ValidateCustom.Ověření v této kategorii lze uplatnit pouze z kódu programu. Další informace naleznete v tématu Vlastní ověření kategorie. |
Kam chcete umístit ověřovací metody
Umístěním ověřovací metoda na jiný typ lze často dosáhnout stejného efektu.Nelze například přidat metodu třídy osoba namísto vztahu ParentsHaveChildren a jeho iterovat odkazy:
[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)
{ ...
Ověření omezení agregaci. Chcete-li použít ověření své místo definujte jeden ověřovací metoda na vlastník třída takové kořenový prvek modelu.Tuto techniku také umožňuje slučovat více zpráv o chybách do jedné zprávy.
Nedostatky jsou kombinované metody je méně snadno spravovat a že omezení musí všechny mají stejné ValidationCategories.Proto doporučujeme, abyste pokud možno zachovat omezení každé zvláštní metody.
Předávání hodnot v kontextu mezipaměti. Parametr kontextu má slovník, do kterého můžete umístit libovolné hodnoty.Slovník přetrvává po dobu spuštění ověření.Zejména ověřovací metodu nelze například zachovat v souvislosti počet chyb a slouží k zamezení zahlcení chybové okno s opakované zprávy.Příklad:
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( ... ); }
Ověření násobnosti
Ověření metody pro kontrolu minimální násobnosti jsou automaticky generovány pro váš modem DSL.Kód je zapsán do Dsl\Generated Code\MultiplicityValidation.cs.Tyto metody se projeví při povolení ověření Editor\Validation uzel v aplikaci Explorer DSL.
Nastavíte-li násobnost roli vztah domény 1.. * nebo 1..1, ale uživatel vytvořit propojení tohoto vztahu se zobrazí chybová zpráva ověření.
Například pokud má vaše DSL třídy osoba a města a vztah PersonLivesInTown vztah 1.. * v roli města pak pro každou osobu, která nemá žádné městě chybová zpráva se zobrazí.
Ověření systémem z programového kódu
Můžete spustit ověření přístupu nebo vytvořením ValidationController.Chyby zobrazený v okně chybové uživateli, použijte ValidationController, připojené k DocData do diagramu.Pokud vytváříte příkaz nabídky, například CurrentDocData.ValidationController je k dispozici ve třídě nastavení příkazu:
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;
...
Další informace naleznete v tématu Jak: přidat příkaz místní nabídky.
Můžete také vytvořit samostatný ověřovací řadič a chyby spravovat sami.Příklad:
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) { ... }
}
Ověření systémem, dojde ke změně
Pokud chcete zajistit, že uživatel je-li model stává neplatným okamžitě varován, můžete definovat úložiště událost, která spouští ověření.Další informace o událostech úložiště, viz Obslužné rutiny událostí rozšířit změny mimo modelu.
Kromě ověřovací kód přidat vlastní kód souboru do vašeho DslPackage projektu s obsahem, podobně jako v následujícím příkladu.Tento kód používá ValidationController připojená k dokumentu.Tento řadič zobrazí chyby ověření platnosti v Visual Studio seznam chyb.
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);
}
}
}
Po zpět nebo znovu operace, které ovlivňují odkazy nebo prvky se také nazývají obslužných rutin.
Vlastní ověření kategorie
Kromě standardní ověření kategorií, například nabídky a otevřený, můžete definovat vlastní kategorie.Tyto kategorie z kódu programu můžete vyvolat.Uživatele nelze vyvolat přímo.
Typické použití pro vlastní kategorie je definovat kategorii, která ověřuje, zda model splňuje předpoklady, zejména nástroje.
Chcete-li přidat metodu ověření do určité kategorie, předponu s atributem takto:
[ValidationMethod(CustomCategory = "PreconditionsForGeneratePartsList")]
[ValidationMethod(ValidationCategory.Menu)]
private void TestForCircularLinks(ValidationContext context)
{...}
[!POZNÁMKA]
Předponu metodu s tolik [ValidationMethod()] atributy, jak chcete.Přidáte-li metodu standardní i vlastní kategorie.
Vyvolat vlastní ověření:
// Invoke all validation methods in a custom category:
validationController.ValidateCustom
(store, // or a list of model elements
"PreconditionsForGeneratePartsList");
Alternativy k ověření
Omezení ověření zprávy o chybách, ale neměňte modelu.Pokud však chcete zabránit vzniku neplatný model, můžete použít jiné techniky.
Tyto postupy však není doporučeno.Je obvykle lepší umožňují uživateli rozhodnout o způsobu odstranění neplatný model.
Upravte změnit obnovení platnosti modelu. Například pokud uživatel nastaví vlastnost nad maximální povolené, je nelze obnovit vlastnost maximální hodnota.Chcete-li to provést, definujte pravidlo.Další informace naleznete v tématu Pravidla rozšířit změny v rámci modelu.
Vrácení transakce je pokusu o neplatný změnit. Můžete také definovat pravidlo pro tento účel, ale v některých případech je možné potlačit vlastnost popisovač OnValueChanging(), nebo potlačení metody jako OnDeleted(). odvolat transakci pomocí this.Store.TransactionManager.CurrentTransaction.Rollback(). Další informace naleznete v Domény vlastnost hodnotu změnit obsluhy.
Upozornění |
---|
Ujistěte se, že uživatel zná byla změna upravena nebo vrátit zpět.Například pomocíSystem.Windows.Forms.MessageBox.Show("message"). |