Definindo uma política de bloqueio para criar segmentos somente leituraDefining a Locking Policy to Create Read-Only Segments

A API de imutabilidade do SDK de modelagem e visualização do Visual Studio permite que um programa bloquear a parte ou todo um modelo de linguagem específica do domínio (DSL), para que ele pode ser lido mas não alterado.The Immutability API of the Visual Studio Visualization and Modeling SDK allows a program to lock part or all of a domain-specific language (DSL) model so that it can be read but not changed. Essa opção somente leitura pode ser usada, por exemplo, para que um usuário pode solicitar colegas para anotar e analisar um modelo de DSL, mas pode não permitir que alterem o original.This read-only option could be used, for example, so that a user can ask colleagues to annotate and review a DSL model but can disallow them from changing the original.

Além disso, como autor de uma DSL, você pode definir um política de bloqueio.In addition, as author of a DSL, you can define a locking policy. Uma política de bloqueio define quais bloqueios são permitidas, não permitido ou obrigatório.A locking policy defines which locks are permitted, not permitted, or mandatory. Por exemplo, quando você publica uma DSL, você pode encorajar os desenvolvedores de terceiros para estendê-lo com novos comandos.For example, when you publish a DSL, you can encourage third-party developers to extend it with new commands. Mas você também pode usar uma política de bloqueio para impedir que alterar o status somente leitura de partes especificadas do modelo.But you could also use a locking policy to prevent them from altering the read-only status of specified parts of the model.

Note

Uma política de bloqueio pode ser evitada por meio de reflexão.A locking policy can be circumvented by using reflection. Ele fornece um limite de claro para os desenvolvedores de terceiros, mas não oferece segurança forte.It provides a clear boundary for third-party developers, but does not provide strong security.

Mais informações e exemplos estão disponíveis no Visual Studio SDK de visualização e modelagem site.More information and samples are available at the Visual Studio Visualization and Modeling SDK website.

Note

No Visual Studio 2017, o transformação de modelo de texto componente é instalado automaticamente como parte do desenvolvimento de extensão do Visual Studio carga de trabalho.In Visual Studio 2017, the Text Template Transformation component is automatically installed as part of the Visual Studio extension devlopment workload. Você também pode instalá-lo do componentes individuais guia do instalador do Visual Studio, sob o ferramentas de código categoria.You can also install it from the Individual components tab of Visual Studio Installer, under the Code tools category. Instalar o SDK de modelagem componente dos componentes individuais guia.Install the Modeling SDK component from the Individual components tab.

Configuração e a obtenção de bloqueiosSetting and Getting Locks

Você pode definir os bloqueios na store, em uma partição ou em um elemento individual.You can set locks on the store, on a partition, or on an individual element. Por exemplo, essa instrução impedirá que um elemento de modelo que está sendo excluído e também impedirá que suas propriedades sejam alteradas:For example, this statement will prevent a model element from being deleted, and will also prevent its properties from being changed:

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

Outros valores do bloqueio podem ser usados para impedir alterações em relações, a criação de elemento, a movimentação entre partições e links de ordenação novamente em uma função.Other lock values can be used to prevent changes in relationships, element creation, movement between partitions, and re-ordering links in a role.

Os bloqueios se aplicam às ações do usuário e ao código de programa.The locks apply both to user actions and to program code. Se o código do programa tenta fazer uma alteração, um InvalidOperationException será lançada.If program code attempts to make a change, an InvalidOperationException will be thrown. Os bloqueios são ignorados em uma operação de desfazer ou refazer.Locks are ignored in an Undo or Redo operation.

Você pode descobrir se um elemento tem um qualquer bloqueio em um determinado conjunto por meio IsLocked(Locks) e você pode obter o conjunto atual de bloqueios em um elemento usando GetLocks().You can discover whether an element has a any lock in a given set by using IsLocked(Locks) and you can obtain the current set of locks on an element by using GetLocks().

Você pode definir um bloqueio sem usar uma transação.You can set a lock without using a transaction. O banco de dados de bloqueio não é parte do repositório.The lock database is not part of the store. Se você definir um bloqueio em resposta a uma alteração de um valor no repositório, por exemplo em OnValueChanged, você deve permitir que as alterações que fazem parte de uma operação de desfazer.If you set a lock in response to a change of a value in the store, for example in OnValueChanged, you should allow changes that are part of an Undo operation.

Esses métodos são métodos de extensão são definidos na Microsoft.VisualStudio.Modeling.Immutability namespace.These methods are extension methods that are defined in the Microsoft.VisualStudio.Modeling.Immutability namespace.

Bloqueios em partições e repositóriosLocks on partitions and stores

Os bloqueios também podem ser aplicados a partições e o armazenamento.Locks can also be applied to partitions and the store. Um bloqueio que é definido em uma partição se aplica a todos os elementos na partição.A lock that is set on a partition applies to all the elements in the partition. Portanto, por exemplo, a instrução a seguir impedirá todos os elementos em uma partição que está sendo excluída, independentemente dos Estados de seus próprios bloqueios.Therefore, for example, the following statement will prevent all the elements in a partition from being deleted, irrespective of the states of their own locks. No entanto, outros bloqueios, como Locks.Property ainda poderia ser definido em elementos individuais:Nevertheless, other locks such as Locks.Property could still be set on individual elements:

partition.SetLocks(Locks.Delete);

Um bloqueio que é definido no Store se aplica a todos os seus elementos, independentemente das configurações de bloqueio em partições e os elementos.A lock that is set on the Store applies to all its elements, irrespective of the settings of that lock on the partitions and the elements.

Uso de bloqueiosUsing Locks

Você pode usar bloqueios para implementar esquemas, como os exemplos a seguir:You could use locks to implement schemes such as the following examples:

  • Não permitir alterações para todos os elementos e relações, exceto aqueles que representam os comentários.Disallow changes to all elements and relationships except those that represent comments. Isso permite que os usuários fazer anotações em um modelo sem alterá-lo.This allows users to annotate a model without changing it.

  • Não permitir alterações na partição padrão, mas permitir que as alterações na partição de diagrama.Disallow changes in the default partition, but allow changes in the diagram partition. O usuário pode reorganizar o diagrama, mas não é possível alterar o modelo subjacente.The user can rearrange the diagram, but cannot alter the underlying model.

  • Não permitir alterações para a Store, exceto para um grupo de usuários que são registrados em um banco de dados separado.Disallow changes to the Store except for a group of users who are registered in a separate database. Para outros usuários, o diagrama e modelo são somente leitura.For other users, the diagram and model are read-only.

  • Não permitir alterações no modelo se uma propriedade booleana do diagrama for definida como true.Disallow changes to the model if a Boolean property of the diagram is set to true. Forneça um comando de menu para alterar essa propriedade.Provide a menu command to change that property. Isso ajuda a garantir que os usuários que não fazem com que as alterações acidentalmente.This helps ensure users that they do not make changes accidentally.

  • Não permitir a adição e exclusão de elementos e relações de classes específicas, mas permitir que as alterações de propriedade.Disallow addition and deletion of elements and relationships of particular classes, but allow property changes. Isso fornece aos usuários um formulário fixado na qual eles podem preencher as propriedades.This provides users with a fixed form in which they can fill the properties.

Valores de bloqueioLock values

Bloqueios podem ser definidos em Store, partição ou ModelElement individual.Locks can be set on a Store, Partition, or individual ModelElement. Bloqueios é um Flags enumeração: você pode combinar seus valores usando '|'.Locks is a Flags enumeration: you can combine its values using '|'.

  • Bloqueios de depósito sempre incluem os bloqueios de sua partição.Locks of a ModelElement always include the Locks of its Partition.

  • Bloqueios de uma partição sempre incluem os bloqueios da Store.Locks of a Partition always include the Locks of the Store.

    Você não pode definir um bloqueio em uma partição ou armazenar e ao mesmo tempo, desabilitar o bloqueio em um elemento individual.You cannot set a lock on a partition or store and at the same time disable the lock on an individual element.

ValorValue Isso significa se IsLocked(Value) é verdadeiroMeaning if IsLocked(Value) is true
NenhumNone Nenhuma restrição.No restriction.
PropriedadeProperty Propriedades do domínio de elementos não podem ser alteradas.Domain properties of elements cannot be changed. Isso não se aplica às propriedades que são geradas pela função de uma classe de domínio em uma relação.This does not apply to properties that are generated by the role of a domain class in a relationship.
AdicionarAdd Novos elementos e links não pode ser criados em uma partição ou armazenar.New elements and links cannot be created in a partition or store.

Não é aplicável à ModelElement.Not applicable to ModelElement.
MoverMove Elemento não pode ser movido entre partições, se element.IsLocked(Move) for true, ou se targetPartition.IsLocked(Move) é verdadeiro.Element cannot be moved between partitions if element.IsLocked(Move) is true, or if targetPartition.IsLocked(Move) is true.
ExcluirDelete Um elemento não pode ser excluído se esse bloqueio é definido no próprio elemento ou em qualquer um dos elementos aos quais seria Propagar exclusão, tais como formas e elementos incorporados.An element cannot be deleted if this lock is set on the element itself, or on any of the elements to which deletion would propagate, such as embedded elements and shapes.

Você pode usar element.CanDelete() para descobrir se um elemento pode ser excluído.You can use element.CanDelete() to discover whether an element can be deleted.
ReordenarReorder A ordenação dos links em um roleplayer não pode ser alterada.The ordering of links at a roleplayer cannot be changed.
RolePlayerRolePlayer O conjunto de links que têm origem em que esse elemento não pode ser alterado.The set of links that are sourced at this element cannot be changed. Por exemplo, os novos elementos não podem ser inseridos nesse elemento.For example, new elements cannot be embedded under this element. Isso não afeta os links para o qual esse elemento é o destino.This does not affect links for which this element is the target.

Se esse elemento é um link, sua origem e destino não são afetados.If this element is a link, its source and target are not affected.
TodosAll OR bit a bit dos outros valores.Bitwise OR of the other values.

Políticas de bloqueioLocking Policies

Como o autor de uma DSL, você pode definir um política de bloqueio.As the author of a DSL, you can define a locking policy. Uma política de bloqueio moderates a operação de SetLocks(), para que você pode impedir bloqueios específicos que está sendo definida ou exigir que os bloqueios específicos devem ser definidos.A locking policy moderates the operation of SetLocks(), so that you can prevent specific locks from being set or mandate that specific locks must be set. Normalmente, você poderia usar uma política de bloqueio de desencorajar os usuários ou desenvolvedores de contravening acidentalmente o uso pretendido de uma DSL, da mesma maneira que você pode declarar uma variável private.Typically, you would use a locking policy to discourage users or developers from accidentally contravening the intended use of a DSL, in the same manner that you can declare a variable private.

Você também pode usar uma política de bloqueio para definir os bloqueios em todos os elementos dependentes de tipo do elemento.You can also use a locking policy to set locks on all elements dependent on the element's type. Isso ocorre porque SetLocks(Locks.None) sempre é chamado quando um elemento é primeiro criado ou desserializado do arquivo.This is because SetLocks(Locks.None) is always called when an element is first created or deserialized from file.

No entanto, você não pode usar uma política para variar os bloqueios em um elemento durante sua vida.However, you cannot use a policy to vary the locks on an element during its life. Para obter esse efeito, você deve usar chamadas para SetLocks().To achieve that effect, you should use calls to SetLocks().

Para definir uma política de bloqueio, você deve:To define a locking policy, you have to:

  • Crie uma classe que implementa ILockingPolicy.Create a class that implements ILockingPolicy.

  • Adicione essa classe para os serviços que estão disponíveis por meio de sua DSL DocData.Add this class to the services that are available through the DocData of your DSL.

Para definir uma política de bloqueioTo define a locking policy

ILockingPolicy tem a seguinte definição:ILockingPolicy has the following definition:

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

Esses métodos são chamados quando é feita uma chamada para SetLocks() em Store, partição ou ModelElement.These methods are called when a call is made to SetLocks() on a Store, Partition, or ModelElement. Em cada método, você receberá um conjunto de propostas de bloqueios.In each method, you are provided with a proposed set of locks. Você pode retornar o conjunto de propostas, ou você pode adicionar e subtrair bloqueios.You can return the proposed set, or you can add and subtract locks.

Por exemplo:For example:

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

Para certificar-se de que os usuários sempre podem excluir elementos, mesmo se outro código chama SetLocks(Lock.Delete):To make sure that users can always delete elements, even if other code calls SetLocks(Lock.Delete):

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

Para não permitir alterações nas propriedades de todos os elementos de MyClass:To disallow change in all the properties of every element of MyClass:

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

Para disponibilizar a política como um serviçoTo make your policy available as a service

No seu DslPackage do projeto, adicione um novo arquivo que contém o código semelhante ao exemplo a seguir:In your DslPackage project, add a new file that contains code that resembles the following example:

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