Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Tartományspecifikus nyelv (DSL) szerzőjeként érvényesítési korlátozásokat határozhat meg annak ellenőrzéséhez, hogy a felhasználó által létrehozott modell értelmezhető-e. Ha például a DSL lehetővé teszi a felhasználók számára, hogy megrajzolhassák az emberek és őseik családfáját, írhat egy kényszert, amely biztosítja, hogy a gyermekeknek a szüleik után születési dátumuk legyen.
Az érvényesítési korlátozások végrehajthatók a modell mentésekor, megnyitásakor és amikor a felhasználó explicit módon futtatja az Ellenőrzés menü parancsot. Az ellenőrzést programvezérléssel is végrehajthatja. Végrehajthat például érvényesítést egy tulajdonságérték vagy kapcsolat változására válaszul.
Az ellenőrzés különösen fontos, ha szöveges sablonokat vagy a felhasználói modelleket feldolgozó egyéb eszközöket ír. Az ellenőrzés biztosítja, hogy a modellek megfelelnek az eszközök által feltételezett előfeltételeknek.
Figyelmeztetés
Azt is engedélyezheti, hogy az érvényesítési korlátozások a DSL külön bővítményeiben, a bővítménymenü parancsaival és a kézmozdulatkezelőkkel együtt definiálhatók legyenek. A felhasználók a DSL mellett is telepíthetik ezeket a bővítményeket. További információ: DSL kiterjesztése MEF használatával.
Érvényesítés futtatása
Ha egy felhasználó egy modellt szerkeszt, vagyis a tartományspecifikus nyelv egy példányát, a következő műveletek futtathatnak érvényesítést:
Kattintson a jobb gombbal a diagramra, és válassza az Összes ellenőrzése lehetőséget.
Kattintson a jobb gombbal a felső csomópontra a DSL Explorerben, és válassza az Összes érvényesítése lehetőséget
Mentse a modellt.
Nyissa meg a modellt.
Emellett olyan programkódot is írhat, amely érvényesítést futtat, például egy menüparancs részeként vagy egy változásra válaszul.
Az érvényesítési hibák megjelennek a Hibalista ablakban. A felhasználó duplán kattinthat egy hibaüzenetre a hiba okaként szolgáló modellelemek kiválasztásához.
Érvényesítési korlátozások meghatározása
Érvényesítési korlátozásokat úgy határozhat meg, hogy érvényesítési módszereket ad hozzá a DSL tartományosztályaihoz vagy kapcsolataihoz. Ha az érvényesítést a felhasználó vagy a program ellenőrzése alatt futtatja, a rendszer végrehajtja az érvényesítési módszerek egy részét vagy egészét. A rendszer minden metódust az osztály minden példányára alkalmaz, és az egyes osztályokban több érvényesítési módszer is lehet.
Minden ellenőrzési módszer jelentést készít a talált hibákról.
Megjegyzés:
Az érvényesítési módszerek hibákat jelentenek, de nem módosítják a modellt. Ha módosítani vagy megakadályozni szeretne bizonyos módosításokat, tekintse meg az Érvényesítés alternatívái című témakört.
Érvényesítési kényszer definiálása
Érvényesítés engedélyezése a Szerkesztő\Érvényesítési csomópontban:
Nyissa meg a Dsl\DslDefinition.dsl fájlt.
A DSL Explorerben bontsa ki a Szerkesztő csomópontot, és válassza az Érvényesítés lehetőséget.
A Tulajdonságok ablakban állítsa a Felhasználás tulajdonságokat a következőre
true: A legkényelmesebb beállítani ezeket a tulajdonságokat.Kattintson az Összes sablon átalakítása gombra a Megoldáskezelő eszköztárán.
Írjon részleges osztálydefiníciókat egy vagy több tartományosztályhoz vagy tartománykapcsolathoz. Ezeket a definíciókat írja be egy új kódfájlba a Dsl-projektben .
Minden osztály előtagja ezzel az attribútummal:
[ValidationState(ValidationState.Enabled)]- Alapértelmezés szerint ez az attribútum engedélyezi a származtatott osztályok érvényesítését is. Ha le szeretné tiltani egy adott származtatott osztály érvényesítését, használhatja
ValidationState.Disableda következőt:
- Alapértelmezés szerint ez az attribútum engedélyezi a származtatott osztályok érvényesítését is. Ha le szeretné tiltani egy adott származtatott osztály érvényesítését, használhatja
Érvényesítési módszerek hozzáadása az osztályokhoz. Minden érvényesítési módszernek lehet bármilyen neve, de egy típusú ValidationContextparamétere lehet.
Az előtagnak egy vagy több
ValidationMethodattribútummal kell rendelkeznie:[ValidationMethod (ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu ) ]Az ValidationCategories határozza meg a metódus végrehajtásának módját.
Például:
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);
}
}
Figyelje meg a következő pontokat a kóddal kapcsolatban:
Érvényesítési módszereket adhat hozzá tartományosztályokhoz vagy tartománykapcsolatokhoz. Az ilyen típusok kódja a Dsl\Generated Code\Domain*.cs.
A rendszer minden érvényesítési módszert alkalmaz az osztály és annak alosztályainak minden egyes példányára. Egy tartománykapcsolat esetén minden példány egy link két modellelem között.
Az érvényesítési módszerek nincsenek alkalmazva semmilyen meghatározott sorrendben, és a rendszer nem alkalmazza az egyes metódusokat az osztály példányaira semmilyen előrejelezhető sorrendben.
Általában helytelen gyakorlat, ha egy érvényesítési módszer frissíti az áruház tartalmát, mert ez inkonzisztens eredményekhez vezetne. Ehelyett a metódusnak minden hibát jelenteni kell a
context.LogError,LogWarningvagyLogInfohívásával.A LogError hívásban megadhatja azon modellelemek vagy kapcsolati hivatkozások listáját, amelyek akkor lesznek kiválasztva, amikor a felhasználó duplán kattint a hibaüzenetre.
A modell programkódban való olvasásáról további információt a Modell navigálása és frissítése a programkódban című témakörben talál.
A példa a következő tartománymodellre vonatkozik. A ParentsHaveChildren kapcsolat gyermek és szülő nevű szerepkörökkel rendelkezik.
Érvényesítési kategóriák
Az attribútumban ValidationMethodAttribute megadhatja, hogy mikor kell végrehajtani az érvényesítési módszert.
| Kategória | Execution |
|---|---|
| ValidationCategories | Amikor a felhasználó meghívja az Ellenőrzés menü parancsot. |
| ValidationCategories | A modellfájl megnyitásakor. |
| ValidationCategories | A fájl mentésekor. Ha ellenőrzési hibák lépnek fel, a felhasználónak lehetősége lesz megszakítani a mentési műveletet. |
| ValidationCategories | A fájl mentésekor. Ha ebben a kategóriában vannak hibák a metódusok között, a rendszer figyelmezteti a felhasználót, hogy előfordulhat, hogy nem lehet újra megnyitni a fájlt. Ez a kategória olyan érvényesítési módszerekhez használható, amelyek ismétlődő neveket vagy azonosítókat tesztelnek, vagy egyéb olyan feltételeket, amelyek betöltési hibákat okozhatnak. |
| ValidationCategories | A ValidateCustom metódus meghívásakor. Az ebben a kategóriában szereplő érvényesítések csak programkódból hívhatók meg. További információ: Egyéni érvényesítési kategóriák. |
Az érvényesítési módszerek helye
Ezt a hatást gyakran úgy érheti el, hogy egy érvényesítési módszert egy másik típusra helyez. Hozzáadhat például egy metódust a Person osztályhoz a ParentsHaveChildren kapcsolat helyett, és iterálhat a kapcsolatokon:
[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)
{ ...
Érvényesítési korlátozások összesítése. Ha kiszámítható sorrendben szeretné alkalmazni az ellenőrzést, definiáljon egyetlen érvényesítési módszert egy tulajdonososztályon, például a modell gyökérelemét. Ezzel a technikával több hibajelentést is összesíthet egyetlen üzenetben.
Hátránya, hogy a kombinált módszer kevésbé könnyen kezelhető, és hogy a korlátozásoknak azonosnak ValidationCategorieskell lenniük . Ezért azt javasoljuk, hogy ha lehetséges, minden kényszert külön metódusban tartson.
Értékek átadása a kontextus gyorsítótárban. A környezeti paraméter rendelkezik egy szótárval, amelybe tetszőleges értékeket helyezhet el. A szótár az érvényesítési futtatás élettartama során is megmarad. Egy adott érvényesítési módszer például megtarthatja a hibaszámot a környezetben, és használatával elkerülheti, hogy ismétlődő üzenetekkel elárasztsa a hibaablakot. Például:
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( ... ); }
A szorzások érvényesítése
A minimális szorzás ellenőrzésére szolgáló érvényesítési módszerek automatikusan létrejönnek a DSL-hez. A kód a Dsl\Generated Code\MultiplicityValidation.cs fájlba van írva. Ezek a módszerek akkor lépnek érvénybe, ha engedélyezi az érvényesítést a Szerkesztő\Ellenőrzés csomópontban a DSL Explorerben.
Ha a tartománykapcsolatok szerepköreinek szorzását 1..* vagy 1..1 értékre állítja, de a felhasználó nem hoz létre kapcsolatot, érvényesítési hibaüzenet jelenik meg.
Ha például a DSL személy és város osztályokkal rendelkezik, és a PersonLivesInTown kapcsolat 1..\* kapcsolattal rendelkezik a Város szerepkörben, akkor minden olyan személynél, akinek nincs városa, hibaüzenet jelenik meg.
Érvényesítés futtatása a programkódból
Az ellenőrzést egy ValidationController elérésével vagy létrehozásával futtathatja. Ha azt szeretné, hogy a hibák megjelenjenek a felhasználó számára a hibaablakban, használja a diagram DocData-fájljához csatolt ValidationControllert. Ha például egy menüparancsot ír, CurrentDocData.ValidationController a parancskészlet osztályban érhető el:
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;
...
További információért lásd a következőt: Parancs hozzáadása a helyi menühöz.
Létrehozhat egy külön érvényesítési vezérlőt is, és saját maga kezelheti a hibákat. Például:
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) { ... }
}
Ellenőrzés futtatása módosítás esetén
Ha meg szeretné győződni arról, hogy a rendszer azonnal figyelmezteti a felhasználót, ha a modell érvénytelenné válik, megadhat egy érvényesítést futtató tárolóeseményt. További információ az áruházi eseményekről a következőben található: Event Handlers Propagate Changes Outside the Model.
Az érvényesítési kód mellett adjon hozzá egy egyéni kódfájlt a DslPackage-projekthez az alábbi példához hasonló tartalommal. Ez a kód a ValidationController dokumentumhoz csatolt kódot használja. Ez a vezérlő megjeleníti az érvényesítési hibákat a Visual Studio hibalistájában.
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);
}
}
}
A kezelőket a csatolásokat vagy elemeket érintő visszavonási vagy újraműveletek után is meghívja a rendszer.
Egyéni érvényesítési kategóriák
A szokásos érvényesítési kategóriákon (például a Menün és a Megnyitáson) kívül saját kategóriákat is meghatározhat. Ezeket a kategóriákat a programkódból hívhatja meg. A felhasználó közvetlenül nem tudja meghívni őket.
Az egyéni kategóriák jellemző használata egy olyan kategória definiálása, amely ellenőrzi, hogy a modell megfelel-e egy adott eszköz előfeltételeinek.
Ha egy érvényesítési metódust szeretne hozzáadni egy adott kategóriához, az előtagot az alábbi attribútummal kell ellátnia:
[ValidationMethod(CustomCategory = "PreconditionsForGeneratePartsList")]
[ValidationMethod(ValidationCategory.Menu)]
private void TestForCircularLinks(ValidationContext context)
{...}
Megjegyzés:
A metódusokat tetszőleges számú [ValidationMethod()] attribútummal előtaggal lehet előtagolni. Testreszabott és standard kategóriákhoz is hozzáadhat metódust.
Egyéni ellenőrzés meghívása:
// Invoke all validation methods in a custom category:
validationController.ValidateCustom
(store, // or a list of model elements
"PreconditionsForGeneratePartsList");
Az érvényesítés alternatívái
Az érvényességi korlátozások hibát jeleznek, de nem módosítják a modellt. Ha ehelyett meg szeretné akadályozni a modell érvénytelenné válását, más technikákat is használhat.
Ezek a technikák azonban nem ajánlottak. Általában jobb, ha hagyja, hogy a felhasználó döntse el, hogyan javítsa ki az érvénytelen modellt.
Módosítsa a módosítást a modell érvényességének visszaállításához. Ha például a felhasználó egy tulajdonságot állít be az engedélyezett maximális érték fölé, visszaállíthatja a tulajdonságot a maximális értékre. Ehhez definiáljon egy szabályt. További információ: Szabályok A változások propagálása a modellen belül.
Ha érvénytelen módosítást kísérel meg, állítsa vissza a tranzakciót. Erre a célra is definiálhat egy szabályt, de bizonyos esetekben felül lehet bírálni egy OnValueChanging() tulajdonságkezelőt, vagy felül lehet bírálni egy olyan módszert, mint például OnDeleted().. A tranzakció visszaállításához használja this.Store.TransactionManager.CurrentTransaction.Rollback().. További információért lásd: Tartománytulajdonság értékváltozás-kezelői.
Figyelmeztetés
Győződjön meg arról, hogy a felhasználó tudja, hogy a módosítást módosították vagy visszaállították. Például: System.Windows.Forms.MessageBox.Show("message").