Ověřování v jazyce specifickém pro doménu
Jako autor jazyka specifické pro doménu (DSL) můžete definovat omezení ověření chcete-li ověřit, zda je model vytvořený uživatelem smysluplné.Například pokud vaše DSL umožňuje uživatelům kreslit řady strom osoby a jejich nadřazených, můžete napsat omezení, který zajišťuje, že podřízené objekty mají data narození po jejich nadřazené položky.
Máte omezení ověření spustit po 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í pod kontrolou programu.Například může provést ověření v reakci na změnu v hodnotě vlastnosti nebo vztah.
Ověření je obzvláště důležité, pokud píšete text šablony nebo jiné nástroje, které zpracovávají modely vaši uživatelé.Ověření zajišťuje, že modely splňují předpoklady, předpokládá se, že pomocí těchto nástrojů.
![]() |
---|
Můžete také povolit ověření omezení, jak jsou definovány v samostatném rozšíření pro vaše DSL společně s příkazy rozšíření nabídky a gesta obslužné rutiny.Uživatelé mohou k instalaci Tato rozšíření kromě vašeho DSL.Další informace naleznete v tématu Rozšíření vašeho DSL pomocí MEF. |
Spuštění ověření
Když uživatel upravuje modelu, to znamená, že instance jazyce specifické pro doménu následující akce lze spustit ověření:
Klikněte pravým tlačítkem myši na diagram a vyberte možnost ověření všechny.
Klikněte pravým tlačítkem myši na nejvyšší uzel v Průzkumníku DSL a vyberte ověření všechny
Uložte model.
Otevřete model.
Kromě toho může zapisovat programový kód, který spouští ověření, například jako součást příkazu nabídky nebo v reakci na změnu.
Všechny chyby ověření se zobrazí v seznam chyb okna.Uživatele můžete dvojitým kliknutím chybovou zprávu a vyberte model elementy, které jsou na příčinu chyby.
Definování omezení ověření
Přidáním metody ověření domény třídy ani vztahy vaše DSL definujete ověření omezení.Při spuštění ověření, uživatelem nebo pod kontrolou programů, jsou spouštěny některé nebo všechny metody ověřování.Každá metoda se použije pro každou instanci své třídy a může být několik metod ověření v 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 neprovádějte změny modelu.Pokud chcete upravit nebo k zabránění některé změny, naleznete v části alternativy k ověření.
Chcete-li definovat omezení ověření
Povolit ověřování v Editor\Validation uzlu:
Otevřít Dsl\DslDefinition.dsl.
V Průzkumníku DSL rozbalte Editor uzel a vyberte ověření.
V okně vlastnosti nastavena používá vlastností, které mají true.Je nejvhodnější k nastavení všech těchto vlastností.
Klikněte na tlačítko transformace všechny šablony v panelu nástrojů Průzkumníka řešení.
Zápis definic dílčí třídu pro jeden nebo více tříd domény nebo domény relace.Zápis do nového souboru kódu v těchto definic Dsl projektu.
Předpona každou třídu s tímto atributem:
[ValidationState(ValidationState.Enabled)]
- Ve výchozím nastavení bude tento atribut také povolit ověřování pro odvozené třídy.Pokud chcete zakázat ověřování pro určité odvozené třídy, můžete použít ValidationState.Disabled.
Přidáte metody ověřování pro třídy.Každá metoda ověření můžete mít libovolný název, ale mít jeden parametr typu ValidationContext.
Musí obsahovat předponu s jedním nebo více ValidationMethod atributy:
[ValidationMethod (ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu ) ]
ValidationCategories určit, kdy metodu provést.
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);
}
}
Informace o tomto kódu následující body:
Metody ověření můžete přidat do domény třídy ani vztahy domény.Kód pro tyto typy je v Dsl\Generated Code\Domain*.cs.
Každá metoda ověření se použije pro všechny instance jeho třídy a jejích podtřídách.V případě vztah domény každá instance je propojení mezi dvěma prvky modelu.
Metody ověření nejsou použity v libovolném pořadí zadaného, a každá metoda není na instance jeho třídy v libovolném pořadí předvídatelný.
Je obvykle chybných vhodné pro metodu ověření pro aktualizaci obsahu úložiště, protože to by vedlo ke nekonzistentní výsledky.Namísto toho ohlásit chyby voláním metody context.LogError, LogWarning nebo LogInfo.
Ve volání LogError může poskytnout seznam prvků modelu nebo vztah odkazy, které budou vybrány při poklepání chybová zpráva.
Informace o tom, jak načíst model v kódu programu naleznete v tématu Navigace v modelu a aktualizace modelu v kódu programu.
V příkladu se vztahuje k následujícím modelu domény.Vztah ParentsHaveChildren obsahuje role, které jsou s názvem podřízenými a nadřazenými.
Ověření kategorie
V ValidationMethodAttribute atributu, určíte, když metoda ověření by měl být spuštěn.
Kategorie |
Spuštění |
---|---|
Pokud uživatel vyvolá příkaz nabídky ověřit. |
|
Při otevření souboru modelu. |
|
Pokud je soubor uložen.Pokud existují chyby ověření, uživatel bude mít možnost zrušení uložení operace. |
|
Pokud je soubor uložen.Pokud existují chyby z metody v této kategorii, uživatel bude upozorněn, že nemusí být možné znovu otevřít soubor. Použijte tuto kategorii pro metody ověřování, které test pro duplicitní názvy nebo ID nebo jiné podmínky, které by mohly způsobit chyby načítání. |
|
Když je volána metoda ValidateCustom.Ověření v této kategorii lze volat pouze z programového kódu. Další informace naleznete v tématu vlastní ověření kategorie. |
Umístění metody ověření
Stejný účinek často dosáhnete tím, že metoda ověření na jiném typu.Například můžete přidat metodu pro třídu osoby namísto vztahu ParentsHaveChildren a se pak iteraci v rámci 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)
{ ...
**Souhrn ověření omezení.**Chcete-li použít ověření v předvídatelný pořadí, definujte jeden ověřovací metodu na třídu vlastníka takových kořenový element modelu.Tato metoda také umožňuje agregace více zpráv o chybách do jedné zprávy.
Nevýhody jsou, kombinované metody je méně usnadňuje správu a že omezení musí všechny mají stejný ValidationCategories.Proto doporučujeme, abyste každý omezení v samostatné metodě, pokud je to možné.
**Předávání hodnot v kontextu mezipaměti.**Parametr kontextu má slovník, do kterého můžete provádět libovolné hodnoty.Slovník trvá po dobu trvání spustit ověření.Konkrétní ověřovací metodu může, například udržovat počtu chyb v kontextu a používat jej nedošlo k zaplavení okna chyb 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ásobnost je automaticky generován pro vaše DSL.Kód je zapsán do Dsl\Generated Code\MultiplicityValidation.cs.Tyto metody vstoupila v platnost při povolení ověřování v Editor\Validation uzel v Průzkumníku DSL.
Pokud nastavíte násobnosti atributu role domény v relaci musí být 1.. * nebo 1..1, ale uživatel není vytvořit odkaz tohoto vztahu se zobrazí chybovou zprávu ověření.
Například pokud má vaše DSL tříd osoby a města a PersonLivesInTown vztah s relací 1.. * v roli městě, pak pro každého uživatele, který nemá žádné městě chybová zpráva se zobrazí.
Spuštění ověření z programového kódu
Ověření můžete spustit přístupu nebo vytvořením ValidationController.Pokud chcete, aby chyby, které mají být zobrazeny v okně chyb uživateli, použijte ValidationController, který je připojen k DocData do diagramu.Pokud píšete příkazu nabídky, například CurrentDocData.ValidationController je k dispozici v sadě třídu 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 Postupy: Přidání příkazu do místní nabídky.
Můžete také vytvořit samostatné ověření řadiče a spravovat chyby 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) { ... }
}
Spuštění ověření, když dojde ke změně
Pokud chcete, aby bylo zajištěno, že uživatel bude-li model se stane neplatným okamžitě upozorněn, můžete definovat úložiště událost, která se spouští ověření.Další informace o události v úložišti, naleznete v části Obslužné rutiny události šíří změny mimo model.
Vedle ověření kódu, 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í 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);
}
}
}
Obslužné rutiny jsou také označován jako po zpět nebo znovu operace, které mají vliv na odkazy nebo elementy.
Vlastní ověření kategorie
Kromě standardní ověření kategorií, jako jsou nabídky a otevřít můžete definovat vlastní kategorie.Můžete vyvolat těchto kategorií z kódu programu.Uživatele nelze vyvolat nich přímo.
Typické použití vlastních kategorií je definovat kategorii, která ověřuje, zda je model splňuje předpoklady konkrétní nástroje.
Chcete-li přidat metodu ověřování pro danou kategorii, předpony s atributem nějak takto:
[ValidationMethod(CustomCategory = "PreconditionsForGeneratePartsList")]
[ValidationMethod(ValidationCategory.Menu)]
private void TestForCircularLinks(ValidationContext context)
{...}
[!POZNÁMKA]
Předpona, metoda s tolik [ValidationMethod()] atributy jak chcete.Metoda můžete přidat vlastní a standardní kategorie.
Chcete-li vyvolat vlastní ověřování:
// Invoke all validation methods in a custom category:
validationController.ValidateCustom
(store, // or a list of model elements
"PreconditionsForGeneratePartsList");
Alternativy k ověření
Omezení ověřovací zprávy o chybách, ale neprovádějte změny modelu.Pokud chcete místo toho zabránit modelu stát neplatný, můžete použít jiné techniky.
Tyto metody však nejsou doporučeny.Je obvykle lepší umožňují uživateli rozhodnout, jak opravit neplatný model.
**Umožňuje upravte změnu k obnovení modelu platnosti.**Například pokud uživatel zadá vlastnost vyšší než maximální povolený, by mohl resetovat vlastnost na maximální hodnotu.Chcete-li to provést, definujte pravidlo.Další informace naleznete v tématu Pravidla šířící změny v modelu.
**Pokud dojde k pokusu o neplatný změny vrátit zpět transakce.**Můžete také definovat pravidlo pro tento účel, ale v některých případech je možné přepsat obslužnou rutinu vlastnost OnValueChanging(), nebo jako například přepsat metodu OnDeleted(). se navrátit transakci, použijte this.Store.TransactionManager.CurrentTransaction.Rollback(). Další informace naleznete v tématu Obslužná rutina změny hodnoty vlastnosti domény.
![]() |
---|
Ujistěte se, že uživatel zná, změnu byl upraven nebo vrátit zpět.Můžete například použít.System.Windows.Forms.MessageBox.Show("message"). |