Udostępnij za pośrednictwem


Sprawdzanie poprawności w języku specyficznym dla domeny

Autor języka specyficznego dla domeny (DSL) można zdefiniować ograniczeń sprawdzania poprawności do sprawdzania, czy model utworzone przez użytkownika jest zrozumiałe.Na przykład Twój DSL umożliwia użytkownikom rysowanie drzewa rodziny osoby i jego elementów nadrzędnych, można zapisać ograniczenie, które gwarantuje, że elementy podrzędne daty urodzenia po jego elementów nadrzędnych.

Może mieć ograniczenia weryfikacji wykonania po zapisaniu modelu, jeśli plik jest otwarty, a po uruchomieniu przez użytkownika w sposób jawny sprawdzania poprawności polecenie menu.Można również wykonywać weryfikacji pod kontrolą programu.Na przykład można wykonać weryfikacji w odpowiedzi na zmianę w wartości właściwości lub relacji.

Weryfikacja jest szczególnie ważne, jeśli podczas pisania tekstu szablonów i inne narzędzia, które przetwarzają użytkowników modelami.Sprawdzanie poprawności zapewnia, że modele spełnić warunków wstępnych, przyjmowana przez te narzędzia.

Informacje dotyczące przestrogiPrzestroga

Można także umożliwić weryfikacji ograniczenia określone w oddzielnych rozszerzenia do swojego DSL, wraz z rozszerzenia poleceń menu i programy obsługi gest.Użytkownik może zdecydować zainstalować te rozszerzenia oprócz swoje DSL.Aby uzyskać więcej informacji, zobacz Rozszerzanie DSL za pomocą MEF.

Uruchamianie sprawdzania poprawności

Gdy użytkownik edytuje modelu, oznacza to, że wystąpienie języka specyficznego dla domeny następujące czynności można uruchomić sprawdzania poprawności:

  • Kliknij prawym przyciskiem myszy diagramu, a następnie wybierz opcję sprawdzić wszystkie.

  • Kliknij prawym przyciskiem myszy węzeł najwyższego w Eksploratorze DSL i wybierz polecenie Sprawdź poprawność wszystkich

  • Zapisz model.

  • Otwórz model.

  • Ponadto można pisać kod program uruchamiany weryfikacji, na przykład w ramach polecenia menu lub w odpowiedzi na zmianę.

Wszystkie błędy weryfikacji pojawi się lista błędów okna.Użytkownik może kliknij dwukrotnie komunikat o błędzie, aby wybrać elementy modelu, które są przyczyną błędu.

Definiowanie ograniczenia sprawdzania poprawności

Definiujemy ograniczenia weryfikacji przez dodanie metody weryfikacji do domeny klas lub relacji z DSL.Po uruchomieniu sprawdzania poprawności przez użytkownika lub pod kontrolą program są wykonywane niektóre lub wszystkie metody weryfikacji.Każda metoda jest stosowana do każdego wystąpienia klasy jego i może istnieć kilka metod weryfikacji w każdej klasy.

Każda metoda weryfikacji zgłasza wszystkie błędy, które zostaną znalezione.

[!UWAGA]

Metody weryfikacji raportowanie błędów, ale nie zmieniaj modelu.Jeśli chcesz dostosować lub zapobiec niektórych zmian, zobacz alternatywy do weryfikacji.

Aby zdefiniować ograniczenie sprawdzania poprawności

  1. Włącz sprawdzanie poprawności w Editor\Validation węzła:

    1. Otwórz Dsl\DslDefinition.dsl.

    2. W Eksploratorze DSL rozwiń edytora a następnie wybierz węzeł weryfikacji.

    3. W oknie dialogowym właściwości ustaw używa właściwości do true.Jest to najbardziej odpowiednim ustawić te właściwości.

    4. Kliknij przycisk Transform wszystkie szablony na pasku narzędzi Eksploratora rozwiązań.

  2. Zapisz definicje częściowej klasy dla jednego lub więcej domeny klas lub relacji domeny.Zapisz te definicje w pliku kodu w Dsl projektu.

  3. Prefiks każdej klasy z tego atrybutu:

    [ValidationState(ValidationState.Enabled)]
    
    • Domyślnie ten atrybut umożliwi sprawdzania poprawności dla klasy pochodnej.Jeśli chcesz wyłączyć weryfikacji dla określonej klasy pochodnej, można użyć ValidationState.Disabled.
  4. Dodaj metody weryfikacji do klasy.Każda metoda weryfikacji mogą mieć dowolną nazwę, ale ma jeden parametr typu ValidationContext.

    Musi być poprzedzona z co najmniej jednym ValidationMethod atrybuty:

    [ValidationMethod (ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu ) ]
    

    ValidationCategories Określ po wykonaniu metody.

Na przykład:

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);
    }
  }

Zwróć uwagę na następujące kwestie dotyczące tego kodu to:

  • Metody sprawdzania poprawności można dodać do domeny klas lub relacji domeny.Kod dla tego typu znajduje się w Dsl\Generated Code\Domain*.cs.

  • Każda metoda weryfikacji jest stosowana do każdego wystąpienia klasy jej i jej podklasy.W przypadku relacji domeny każde wystąpienie jest łącze między dwoma elementami modelu.

  • Metody weryfikacji nie są stosowane w dowolnej kolejności, a każda metoda nie ma zastosowania do wystąpienia klasy, jego w dowolnej kolejności wartości prognozowanych.

  • Jest on zwykle zły praktyki metodę weryfikacji, aby zaktualizować zawartość magazynu, ponieważ to prowadzić do niezgodne wyniki.Zamiast tego raportu jakiegokolwiek błędu przez wywołanie metody context.LogError, LogWarning lub LogInfo.

  • W wywołaniu LogError można podać listę elementów modelu lub relacji łączy, które można wybrać, gdy użytkownik kliknie dwukrotnie komunikat o błędzie.

  • Informacje na temat odczytu modelu w kodzie programu, zobacz Nawigowanie i aktualizowanie modelu w kodzie programu.

Przykład dotyczy następujących modelu domeny.Relacja ParentsHaveChildren ma ról, które są nazywane nadrzędnym a podrzędnym.

Diagram DSL Definition - model drzewa rodziny

Sprawdzanie poprawności kategorii

W ValidationMethodAttribute atrybutu, określić, jeśli mają zostać wykonane metodę weryfikacji.

Kategoria

Wykonanie

Menu

Gdy użytkownik wywołuje polecenie sprawdzania poprawności.

Open

Po otwarciu pliku modelu.

Save

Jeśli plik jest zapisywany.Jeśli występują błędy sprawdzania poprawności, użytkownik będzie miał możliwość anulowanie Zapisywanie operacji.

Load

Jeśli plik jest zapisywany.W przypadku błędów z metod w tej kategorii użytkownika jest ostrzeżenie, że może nie być możliwe ponownie otwórz plik.

Użyj tej kategorii dla weryfikacji metody testujące zduplikowane nazwy lub identyfikatory lub inne warunki, które mogą powodować błędy podczas ładowania.

Custom

Gdy jest wywoływana metoda ValidateCustom.Liczba ocen w tej kategorii można wywołać tylko z kodu programu.

Aby uzyskać więcej informacji, zobacz niestandardowe weryfikacji kategorii.

Gdzie umieścić metody weryfikacji

Często można osiągnąć ten sam efekt, umieszczając metodę weryfikacji o różnych typach.Na przykład można dodać metodę do klasy zamiast relacji ParentsHaveChildren osoby i została ona iterację łącza:

[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)
        { ...

**Agregację ograniczenia weryfikacji.**Aby zastosować weryfikacji w ustalonym porządku, należy zdefiniować metodę weryfikacji pojedynczy w klasie właściciela, taki element główny modelu.Ta metoda umożliwia także Agreguj kilka raportów o błędach do pojedynczej wiadomości.

Minusy są, czy metoda jest mniej łatwy w zarządzaniu i że ograniczenia należy wszystkie mają taki sam ValidationCategories.Dlatego zaleca się zachować każde ograniczenie w osobnym metody, jeśli to możliwe.

**Przekazanie wartości w pamięci podręcznej kontekstu.**Parametr kontekstu ma słownika, do którego można umieścić dowolne wartości.Słownik utrzymuje się przez cały okres istnienia Uruchom weryfikacji.Metodę weryfikacji określonego można na przykład zachować liczby błędów w tym kontekście i umożliwia uniknąć przepełnienia oknie błędów z powtarzanego wiadomości.Na przykład:

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( ... ); }

Sprawdzanie poprawności Liczebność punktów

Metody weryfikacji sprawdzania minimalna liczebności są automatycznie generowane dla swojego DSL.Kod jest zapisywana w Dsl\Generated Code\MultiplicityValidation.cs.Te metody zastosowane podczas włączania weryfikacji w Editor\Validation węzła w Eksploratorze DSL.

Jeśli ustawisz Liczebność roli relacji domeny musi wynosić 1.. * lub 1..1, ale użytkownik nie tworzy łącze tej relacji, pojawi się komunikat o błędzie sprawdzania poprawności.

Na przykład, jeśli Twój DSL ma klas osoby i miejscowości i relacji PersonLivesInTown przy użyciu relacji 1.. * w roli miejscowość to dla poszczególnych osób, które ma nie odbędzie się komunikat o błędzie pojawi się.

Uruchomiono sprawdzania poprawności z kodu programu

Uzyskując dostęp do lub tworzenia ValidationController można uruchomić sprawdzania poprawności.Błędy, które mają być wyświetlane w oknie błędów do użytkownika, należy użyć ValidationController, dołączonego do DocData do diagramu.Na przykład, jeśli piszesz poleceniu menu CurrentDocData.ValidationController jest dostępna w tej klasie zestaw poleceń:

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; 
...

Aby uzyskać więcej informacji, zobacz Porady: dodawanie polecenia do menu skrótów.

Można również utworzyć kontroler oddzielne weryfikacji i samodzielnie zarządzać błędy.Na przykład:

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) { ... }
}

Uruchamianie weryfikacji w przypadku zmiany

Jeśli chcesz upewnić się, że użytkownik jest niezwłocznie powiadamiany w przypadku modelu staje się nieprawidłowy, można zdefiniować zdarzenia magazynu, działającym weryfikacji.Aby uzyskać więcej informacji o zdarzeniach magazynu, zobacz Programy obsługi zdarzeń propagujące zmiany poza modelem.

Oprócz kod sprawdzania poprawności, należy dodać plik kodu niestandardowego do swojego DslPackage projektu z zawartością, podobnie jak w poniższym przykładzie.Ten kod zawiera ValidationController dołączony do dokumentu.Ten kontroler wyświetla błędy sprawdzania poprawności w Visual Studio lista błędów.

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);
    }
  }
} 

Programy obsługi są również nazywane po operacji cofania lub wykonywania ponownego, które wpływa na łącza lub elementy.

Kategorie niestandardowego sprawdzania poprawności

Oprócz kategorii standardowe weryfikacji, takich jak Menu i otwórz można definiować własne kategorie.Można ją wywołać tych kategoriach z kodu programu.Użytkownik nie mogą wywoływać ich bezpośrednio.

Typowym zastosowaniem własne kategorie jest do definiowania kategorii, który umożliwia sprawdzenie, czy model spełnia warunków wstępnych określonego narzędzia.

Aby dodać metodę weryfikacji do określonej kategorii, należy poprzedzić go z atrybutem w taki sposób:

[ValidationMethod(CustomCategory = "PreconditionsForGeneratePartsList")]
[ValidationMethod(ValidationCategory.Menu)] 
private void TestForCircularLinks(ValidationContext context) 
{...}

[!UWAGA]

Można prefiks metody z dowolną liczbę [ValidationMethod()] atrybuty żądanej.Metodę można dodać do kategorii standardowymi i niestandardowymi.

Aby wywołać niestandardowego sprawdzania poprawności:

// Invoke all validation methods in a custom category: 
validationController.ValidateCustom
  (store, // or a list of model elements
   "PreconditionsForGeneratePartsList");

Alternatywy do sprawdzania poprawności

Sprawdzanie poprawności ograniczenia raportowanie błędów, ale nie zmieniaj modelu.Jeśli jednak chcesz zapobiec modelu staje się nieprawidłowy, można użyć innych technik.

Jednak nie zaleca się skorzystanie z tych metod.Zazwyczaj najlepiej umożliwia użytkownikowi na określenie sposobu Popraw nieprawidłowe modelu.

**Dostosuj zmiany do przywrócenia modelu do ważności.**Na przykład jeśli użytkownik ustawia właściwości powyżej maksymalną dozwoloną, można zresetować właściwości wartość maksymalna.W tym celu należy zdefiniować regułę.Aby uzyskać więcej informacji, zobacz Reguły propagujące zmiany w modelu.

**Wycofać transakcji próbie zmiany nieprawidłowe.**W tym celu można również zdefiniować regułę, ale w niektórych przypadkach użytkownik może zastąpić właściwość program obsługi OnValueChanging(), lub aby zastąpić metody, takie jak OnDeleted(). można wycofać transakcji, użyj this.Store.TransactionManager.CurrentTransaction.Rollback(). uzyskać więcej informacji, zobacz Obsługa zmian wartości właściwości domeny.

Informacje dotyczące przestrogiPrzestroga

Upewnij się, że użytkownik wie, że zmiana została dostosowana lub wycofana.Na przykład użyćSystem.Windows.Forms.MessageBox.Show("message").

Zobacz też

Koncepcje

Nawigowanie i aktualizowanie modelu w kodzie programu

Programy obsługi zdarzeń propagujące zmiany poza modelem