Definiowanie zasad blokowania na potrzeby tworzenia segmentów tylko do odczytu

Interfejs API niezmienności zestawu SDK wizualizacji i modelowania usługi Visual Studio umożliwia programowi zablokowanie części lub całego modelu języka specyficznego dla domeny (DSL), aby można go było odczytać, ale nie zmienić. Ta opcja tylko do odczytu może być używana na przykład tak, aby użytkownik mógł poprosić współpracowników o adnotacje i przejrzenie modelu DSL, ale może nie zezwalać im na zmianę oryginalnego.

Ponadto, jako autor DSL, można zdefiniować zasady blokowania. Zasady blokowania określają, które blokady są dozwolone, niedozwolone lub obowiązkowe. Na przykład podczas publikowania DSL można zachęcić deweloperów innych firm do rozszerzenia go o nowe polecenia. Można jednak również użyć zasad blokowania, aby uniemożliwić im zmianę stanu tylko do odczytu określonych części modelu.

Uwaga

Zasady blokowania można obejść za pomocą odbicia. Zapewnia ona jasne granice dla deweloperów innych firm, ale nie zapewnia silnego bezpieczeństwa.

Więcej informacji i przykładów można znaleźć w witrynie internetowej Visual Studio Visualization and Modeling SDK (Wizualizacja i modelowanie).

Uwaga

Składnik transformacji szablonu tekstu jest automatycznie instalowany w ramach obciążenia programistycznego rozszerzenia programu Visual Studio . Można go również zainstalować z karty poszczególne składniki Instalator programu Visual Studio, w obszarze zestawy SDK, biblioteki i struktury . Zainstaluj składnik Modeling SDK na karcie poszczególne składniki .

Ustawianie i pobieranie blokad

Blokady można ustawić w magazynie, na partycji lub w jednym elemencie. Na przykład ta instrukcja uniemożliwi usunięcie elementu modelu, a także zapobiegnie zmianie jego właściwości:

using Microsoft.VisualStudio.Modeling.Immutability; ...
element.SetLocks(Locks.Delete | Locks.Property);

Inne wartości blokady mogą służyć do zapobiegania zmianom w relacjach, tworzeniu elementów, poruszaniu się między partycjami i zmienianiu kolejności linków w roli.

Blokady dotyczą zarówno akcji użytkownika, jak i kodu programu. Jeśli kod programu spróbuje wprowadzić zmianę, InvalidOperationException zostanie zgłoszony wyjątek . Blokady są ignorowane w operacji Cofnij lub Ponownie wycofywuj.

Możesz sprawdzić, czy element ma blokadę w danym zestawie, używając elementu , i uzyskać bieżący zestaw blokad elementu IsLocked(Locks) za pomocą . GetLocks()

Blokadę można ustawić bez użycia transakcji. Baza danych blokady nie jest częścią magazynu. Jeśli ustawiono blokadę w odpowiedzi na zmianę wartości w magazynie, na przykład w funkcji OnValueChanged, należy zezwolić na zmiany, które są częścią operacji Cofnij.

Te metody są metodami rozszerzeń zdefiniowanymi w przestrzeni Microsoft.VisualStudio.Modeling.Immutability nazw .

Blokady na partycjach i magazynach

Blokady można również stosować do partycji i magazynu. Blokada ustawiona na partycji ma zastosowanie do wszystkich elementów w partycji. W związku z tym na przykład następująca instrukcja uniemożliwi usunięcie wszystkich elementów w partycji, niezależnie od stanów ich własnych blokad. Niemniej jednak inne blokady, takie Locks.Property jak, nadal można ustawić dla poszczególnych elementów:

partition.SetLocks(Locks.Delete);

Blokada ustawiona w magazynie ma zastosowanie do wszystkich jej elementów, niezależnie od ustawień tej blokady w partycjach i elementach.

Używanie blokad

Blokad można użyć do zaimplementowania schematów, takich jak następujące przykłady:

  • Nie zezwalaj na zmiany wszystkich elementów i relacji z wyjątkiem tych, które reprezentują komentarze. Dzięki temu użytkownicy mogą adnotacji modelu bez jego zmiany.

  • Nie zezwalaj na zmiany w partycji domyślnej, ale zezwalaj na zmiany w partycji diagramu. Użytkownik może zmienić rozmieszczenie diagramu, ale nie może zmienić bazowego modelu.

  • Nie zezwalaj na zmiany w sklepie z wyjątkiem grupy użytkowników, którzy są zarejestrowani w oddzielnej bazie danych. W przypadku innych użytkowników diagram i model są tylko do odczytu.

  • Nie zezwalaj na zmiany w modelu, jeśli właściwość logiczna diagramu jest ustawiona na wartość true. Podaj polecenie menu, aby zmienić właściwość. Dzięki temu użytkownicy nie będą przypadkowo wprowadzać zmian.

  • Nie zezwalaj na dodawanie i usuwanie elementów oraz relacji określonych klas, ale zezwalaj na zmiany właściwości. Dzięki temu użytkownicy mają stały formularz, w którym mogą wypełniać właściwości.

Zablokuj wartości

Blokady można ustawić dla magazynu, partycji lub pojedynczego elementu ModelElement. Blokady to Flags wyliczenie: można połączyć jego wartości przy użyciu |.

  • Blokady elementu ModelElement zawsze zawierają blokady jego partycji.

  • Blokady partycji zawsze zawierają blokady magazynu.

    Nie można ustawić blokady partycji lub magazynu i jednocześnie wyłączyć blokady pojedynczego elementu.

Wartość Oznacza to, że IsLocked(Value) jeśli wartość jest prawdziwa
Brak Brak ograniczeń.
Właściwość Nie można zmienić właściwości domeny elementów. Nie dotyczy to właściwości generowanych przez rolę klasy domeny w relacji.
Dodaj Nowych elementów i linków nie można tworzyć w partycji ani magazynie.

Nie dotyczy ModelElement .
Move Nie można przenosić elementu między partycjami, element.IsLocked(Move) jeśli ma wartość true lub jeśli ma wartość targetPartition.IsLocked(Move) true.
Usuń Nie można usunąć elementu, jeśli ta blokada jest ustawiona na samym elemencie lub na dowolnym elemencie, do którego miałoby zostać rozpropagowane usunięcie, takim jak osadzone elementy i kształty.

Umożliwia element.CanDelete() wykrywanie, czy można usunąć element.
Zmienić kolejność Nie można zmienić kolejności linków u użytkownika roleplayer.
RolePlayer Nie można zmienić zestawu linków, które pochodzą z tego elementu. Na przykład nie można osadzić nowych elementów w tym elemencie. Nie ma to wpływu na łącza, dla których ten element jest elementem docelowym.

Jeśli ten element jest łączem, nie ma to wpływu na jego element źródłowy i docelowy.
Wszystko Bitowe OR innych wartości.

Blokowanie zasad

Jako autor DSL, można zdefiniować zasady blokowania. Zasady blokowania moderują działanie mechanizmu SetLocks(), dzięki czemu można zapobiec ustawianiu określonych blokad lub nakłonić do ustawienia określonych blokad. Zazwyczaj należy użyć zasad blokowania, aby zniechęcić użytkowników lub deweloperów przed przypadkowym naruszeniem zamierzonego użycia DSL w taki sam sposób, jak można zadeklarować zmienną private .

Można również użyć zasad blokowania, aby ustawić blokady dla wszystkich elementów zależnych od typu elementu. Dzieje się SetLocks(Locks.None) tak, ponieważ jest zawsze wywoływana, gdy element jest tworzony po raz pierwszy lub deserializowany z pliku.

Nie można jednak użyć zasad, aby zmieniać blokady elementu w trakcie jego życia. Aby osiągnąć ten efekt, należy użyć wywołań funkcji SetLocks() .

Aby zdefiniować zasady blokowania, należy:

  • Utwórz klasę, która implementuje ILockingPolicy klasę .

  • Dodaj tę klasę do usług, które są dostępne za pośrednictwem docData dsl.

Aby zdefiniować zasady blokowania

ILockingPolicy ma następującą definicję:

public interface ILockingPolicy
{
  Locks RefineLocks(ModelElement element, Locks proposedLocks);
  Locks RefineLocks(Partition partition, Locks proposedLocks);
  Locks RefineLocks(Store store, Locks proposedLocks);
}

Te metody są wywoływane, gdy wywoływane jest wywołanie metody SetLocks() w magazynie, partycji lub elementie ModelElement. W każdej metodzie jest dostarczany proponowany zestaw blokad. Możesz zwrócić proponowany zestaw lub dodać i odjąć blokady.

Na przykład:

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Immutability;
namespace Company.YourDsl.DslPackage // Change
{
  public class MyLockingPolicy : ILockingPolicy
  {
    /// <summary>
    /// Moderate SetLocks(this ModelElement target, Locks locks)
    /// </summary>
    /// <param name="element">target</param>
    /// <param name="proposedLocks">locks</param>
    /// <returns></returns>
    public Locks RefineLocks(ModelElement element, Locks proposedLocks)
    {
      // In my policy, users can never delete an element,
      // and other developers cannot easily change that:
      return proposedLocks | Locks.Delete);
    }
    public Locks RefineLocks(Store store, Locks proposedLocks)
    {
      // Only one user can change this model:
      return Environment.UserName == "aUser"
           ? proposedLocks : Locks.All;
    }

Aby upewnić się, że użytkownicy mogą zawsze usuwać elementy, nawet jeśli inne wywołania kodu SetLocks(Lock.Delete):

return proposedLocks & (Locks.All ^ Locks.Delete);

Aby nie zezwalać na zmianę we wszystkich właściwościach każdego elementu Klasy MyClass:

return element is MyClass ? (proposedLocks | Locks.Property) : proposedLocks;

Aby udostępnić zasady jako usługę

W DslPackage projekcie dodaj nowy plik zawierający kod podobny do poniższego przykładu:

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Immutability;
namespace Company.YourDsl.DslPackage // Change
{
  // Override the DocData GetService() for this DSL.
  internal partial class YourDslDocData // Change
  {
    /// <summary>
    /// Custom locking policy cache.
    /// </summary>
    private ILockingPolicy myLockingPolicy = null;

    /// <summary>
    /// Called when a service is requested.
    /// </summary>
    /// <param name="serviceType">Service requested</param>
    /// <returns>Service implementation</returns>
    public override object GetService(System.Type serviceType)
    {
      if (serviceType == typeof(SLockingPolicy)
       || serviceType == typeof(ILockingPolicy))
      {
        if (myLockingPolicy == null)
        {
          myLockingPolicy = new MyLockingPolicy();
        }
        return myLockingPolicy;
      }
      // Request is for some other service.
      return base.GetService(serviceType);
    }
}