Definir uma diretiva de bloqueio para criar segmentos de somente leitura

A API de imutabilidade da Visual Studio SDK de modelagem e visualização permite que um programa para bloqueio de parte ou todo um modelo de linguagem específica de domínio (DSL) para que ele pode ser lido mas não alterado.Esta opção somente leitura pode ser usada, por exemplo, para que um usuário pode pedir a seus colegas para anotar e analisar um modelo DSL, mas poderá desautorizar alterem o original.

Além disso, como autor de uma DSL, você pode definir um o bloqueio de diretiva. Uma diretiva de bloqueio define quais os bloqueios são permitidos, não permitidos ou obrigatórios.Por exemplo, quando você publica uma DSL, você pode incentivar os desenvolvedores de terceiros para estendê-la com novos comandos.Mas você também pode usar uma diretiva de bloqueio para impedir que eles alterem o status somente leitura de peças especificadas do modelo.

ObservaçãoObservação

Uma diretiva de bloqueio pode ser evitada por meio de reflexão.Ele fornece um limite claro para desenvolvedores de terceiros, mas não fornece segurança forte.

Mais informações e exemplos estão disponíveis na Visual StudioSDK de modelagem e visualização site da Web. 

Configuração e obtenção de bloqueios

Você pode definir os bloqueios no armazenamento, em uma partição ou em um elemento individual.Por exemplo, essa instrução impedirá que um elemento de modelo seja excluído e também evitará suas propriedades sejam alteradas:

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

Outros valores de bloqueio podem ser usados para impedir alterações nas relações, a criação do elemento, a movimentação entre partições e re-ordering links em uma função.

Os bloqueios se aplicam às ações do usuário e código de programa.Se o código de programa tenta fazer uma alteração, um InvalidOperationException será lançada.Os bloqueios são ignorados em uma operação de desfazer ou refazer.

Você pode descobrir se um elemento tem um bloqueio de qualquer em um determinado conjunto por meio de IsLocked(Locks) e você pode obter o conjunto atual de bloqueios em um elemento usando GetLocks().

Você pode definir um bloqueio sem usar uma transação.O banco de dados de bloqueio não é parte do armazenamento.Se você definir um bloqueio em resposta a uma alteração de um valor no armazenamento, por exemplo no OnValueChanged, você deve permitir que as alterações que fazem parte de uma operação de desfazer.

Esses métodos são métodos de extensão são definidos na Microsoft.VisualStudio.Modeling.Immutability espaço para nome.

Ff521896.collapse_all(pt-br,VS.110).gifBloqueios em partições e armazenamentos

Bloqueios também podem ser aplicados às partições e o armazenamento.Um bloqueio que é definido em uma partição se aplica a todos os elementos na partição.Portanto, por exemplo, a instrução a seguir impedirá todos os elementos em uma partição que está sendo excluído, independentemente dos Estados de seus próprios bloqueios.No entanto, outros bloqueios, como Locks.Property ainda poderia ser definido em elementos individuais:

partition.SetLocks(Locks.Delete);

Um bloqueio que é definido no armazenamento se aplica a todos os seus elementos, independentemente das configurações desse bloqueio sobre as partições e os elementos.

Ff521896.collapse_all(pt-br,VS.110).gifUsando bloqueios

Você poderia usar bloqueios para implementar esquemas como, por exemplo, os exemplos a seguir:

  • Não permitir alterações em todos os elementos e relações, exceto aqueles que representam os comentários.Isso permite aos usuários fazer anotações em um modelo sem alterá-lo.

  • Não permitir alterações na partição padrão, mas permitir alterações na partição do diagrama.O usuário pode reorganizar o diagrama, mas não é possível alterar o modelo subjacente.

  • Não permitir alterações no armazenamento, exceto para um grupo de usuários registrados em um banco de dados separado.Para outros usuários, o diagrama e o modelo são somente leitura.

  • Não permitir alterações no modelo se uma propriedade booleana do diagrama estiver definida como true.Fornece um comando de menu para alterar essa propriedade.Isso ajuda a garantir que os usuários que não faça as alterações acidentalmente.

  • Não permitir a adição e exclusão de elementos e relações de classes específicas, mas permitir alterações de propriedade.Isso fornece aos usuários uma forma fixa no qual eles poderão preencher as propriedades.

Valores de bloqueio

Os bloqueios podem ser definidos em uma loja, a partição ou o ElementoModelo individual.Bloqueios é um Flags enumeração: você pode combinar os seus valores usando ' |'.

  • Bloqueios de um ModelElement sempre incluem os bloqueios de sua partição.

  • Bloqueios de uma partição sempre incluem os bloqueios do armazenamento.

Você não pode definir um bloqueio em uma partição ou armazenar e ao mesmo tempo, desativar o bloqueio em um elemento individual.

Valor

Ou seja, se IsLocked(Value) é verdadeiro

Nenhum

Sem restrição.

Propriedade

Propriedades dos elementos de domínio não podem ser alteradas.Isso não se aplica às propriedades que são geradas pela função de uma classe de domínio em um relacionamento.

Adicionar

Não é possível criar novos elementos e links em uma partição ou armazenar.

Não aplicável a ModelElement.

Mover

Elemento não pode ser movido entre partições se element.IsLocked(Move) for verdadeira, ou se targetPartition.IsLocked(Move) é verdadeiro.

Excluir

Um elemento não pode ser excluído se este bloqueio é definido no elemento propriamente dito, ou em qualquer um dos elementos aos quais seria Propagar exclusão, como formas e elementos incorporados.

Você pode usar element.CanDelete() para descobrir se um elemento pode ser excluído.

Reordenar

A ordenação dos links em um roleplayer não pode ser alterada.

RolePlayer

O conjunto de links que são originados por este elemento não pode ser alterado.Por exemplo, os novos elementos não podem ser incorporados sob esse elemento.Isso não afeta os links para o qual este elemento é o destino.

Se este elemento for um link, sua origem e destino não são afetados.

Todos

Bit a bit ou os outros valores.

Políticas de bloqueio

Como o autor de um DSL, você pode definir um a política de bloqueamento.Uma diretiva de bloqueio moderates a operação do SetLocks(), para que você pode impedir bloqueios específicos que está sendo definida ou exigem que os bloqueios específicos devem ser definidos.Normalmente, você usaria uma diretiva de bloqueio para desencorajar os usuários ou desenvolvedores de acidentalmente contravening o uso pretendido de uma DSL, da mesma maneira que você pode declarar uma variável private.

Você também pode usar uma diretiva de bloqueio para definir os bloqueios em todos os elementos depende do tipo do elemento.Isso ocorre porque SetLocks(Locks.None) é chamado quando um elemento é criado pela primeira vez ou desserializado a partir do arquivo.

No entanto, você não pode usar uma diretiva para variar os bloqueios em um elemento durante sua vida.Para obter esse efeito, você deve usar chamadas para SetLocks().

Para definir uma diretiva de bloqueio, você deve:

  • Criar uma classe que implementa ILockingPolicy.

  • Adicione esta classe para os serviços que estão disponíveis através do DocData de seu DSL.

Ff521896.collapse_all(pt-br,VS.110).gifPara definir uma diretiva de bloqueio

ILockingPolicytem a seguinte definição:

  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 uma loja, a partição ou o ElementoModelo.Cada método, você é fornecidos com um conjunto de propostas de bloqueios.Você pode retornar o conjunto de propostas, ou você pode adicionar e subtrair bloqueios.

Por exemplo:

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 poderão excluir elementos, mesmo que outro código chamaSetLocks(Lock.Delete):

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

Para impedir a alteração em todas as propriedades de cada elemento de MyClass:

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

Ff521896.collapse_all(pt-br,VS.110).gifPara disponibilizar sua política como um serviço

No seu DslPackage de projeto, adicione um novo arquivo que contém código semelhante ao exemplo a seguir:

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