Personalizar o comportamento de exclusão
A exclusão de um elemento geralmente faz com que os elementos relacionados também seja excluído.Todas as relações são conectados a ele, e quaisquer elementos filho são excluídos.Esse comportamento é denominado Excluir propagação.Você pode personalizar a propagação de exclusão, por exemplo organizar o que os elementos relacionados adicionais serão excluídos.Escrevendo código de programa, você pode fazer a propagação de excluir dependem do estado do modelo.Você também pode causar outras alterações ocorrem em resposta a uma exclusão.
Este tópico inclui as seguintes seções:
Comportamento de exclusão padrão
Definindo a opção Propagar excluir de uma função
Substituindo o fechamento excluir – usar essa técnica onde a exclusão pode levar à exclusão de elementos de vizinhos.
Usando OnDeleting e OnDeleted – usar esses métodos onde a resposta poderia incluir outras ações como, por exemplo, atualizando um valor dentro ou fora do armazenamento.
Regras de exclusão – usar regras para propagar atualizações de qualquer tipo em armazenamento, onde uma alteração pode levar a outras pessoas.
Eventos de exclusão – eventos de uso de armazenamento para propagar atualizações fora o armazenamento, por exemplo, para outros Visual Studio documentos.
UnMerge – use a operação de UnMerge para desfazer a operação de mesclagem anexado a um elemento filho a seu pai.
Comportamento de exclusão padrão
Por padrão, as seguintes regras orientam a propagação de exclusão:
Se um elemento for excluído, todos os elementos incorporados também serão excluídos.Os elementos incorporados são aqueles que são os alvos de incorporar as relações para o qual este elemento é a fonte.Por exemplo, se houver uma relação de incorporação do álbum de música, em seguida, quando um determinado álbum é excluído, todas as suas músicas serão também excluídas.
Por outro lado, a exclusão de uma música não exclui o álbum.
Por padrão, a exclusão não propaga ao longo de relações de referência.Se houver uma relação de referência ArtistPlaysOnAlbum do álbum para o artista, a exclusão de um álbum não exclui qualquer artista relacionada e a exclusão de um artista não exclui qualquer álbum.
No entanto, a exclusão propagar junto alguns relacionamentos internos.Por exemplo, quando um elemento de modelo é excluído, sua forma no diagrama também será excluída.O elemento e a forma estão relacionadas a PresentationViewsSubject relação de referência.
Cada relação que está conectada ao elemento, em função de origem ou destino, é excluída.A propriedade da função do elemento em que a função oposta não contém o elemento excluído.
Definindo a opção Propagar excluir de uma função
Você pode causar a exclusão se propaguem ao longo de uma relação de referência, ou de um filho de incorporado para seu pai.
Para definir a propagação de exclusão
No diagrama de definição de DSL, selecione o função para o qual você deseja que a propagação para excluir.A função é representada pela linha à esquerda ou à direita de uma caixa de relação de domínio.
Por exemplo, se você quiser especificar que sempre que um álbum é excluído, os artistas relacionados também serão excluídos e selecionam a função conectada à classe de domínio do artista.
Na janela Properties, defina a Propaga excluir propriedade.
Pressione F5 e verifique se:
Quando uma instância dessa relação é excluída, o elemento na função selecionada também será excluído.
Quando um elemento em que a função oposta é excluído, instâncias desse relacionamento serão excluídas e os elementos relacionados a esta função serão excluídos.
Você também pode ver o Propaga excluir de opção na DSL detalhes janela.Selecione uma classe de domínio e, na janela de detalhes de DSL, abra o Excluir comportamento página clicando no botão ao lado da janela.O propagar opção é mostrada para a função oposta de cada relação.O Excluir estilo coluna indica se o propagar opção é na sua configuração padrão, mas não tem qualquer efeito separado.
Excluir a propagação por meio de código de programa
As opções no arquivo de definição de DSL só permitem que você escolha se a exclusão se propaga para um vizinho de imediato.Para implementar um esquema mais complexo de propagação de exclusão, você pode escrever o código de programa.
Observação |
---|
Para adicionar o código de programa à sua definição de DSL, crie um arquivo de código separados na Dsl de projeto e gravar definições parciais para aumentar as classes na pasta do código gerado.Para obter mais informações, consulte Escrever código para personalizar uma linguagem específica de domínio. |
Definindo um fechamento de exclusão
A operação de exclusão usa a classe YourModelDeleteClosure para determinar quais elementos para excluir, dada uma seleção inicial.Ele chama ShouldVisitRelationship() e ShouldVisitRolePlayer() repetidamente, orientando o gráfico de relações.Você pode substituir esses métodos.ShouldVisitRolePlayer é fornecido com a identidade de um link e o elemento em uma das funções do link.Ele deve retornar um dos seguintes valores:
VisitorFilterResult.Yes– O elemento deve ser excluído e o walker deve prosseguir para tentar o elemento de outros links.
VisitorFilterResult.DoNotCare– O elemento não deve ser excluído, a menos que outra consulta responde que deve ser excluído.
VisitorFilterResult.Never– O elemento não deve ser excluído, mesmo que responde a outra consulta Yes, e o walker não deve tentar o elemento de outros links.
// When a musician is deleted, delete their albums with a low rating.
// Override methods in <YourDsl>DeleteClosure in DomainModel.cs
partial class MusicLibDeleteClosure
{
public override VisitorFilterResult ShouldVisitRolePlayer
(ElementWalker walker, ModelElement sourceElement, ElementLink elementLink,
DomainRoleInfo targetDomainRole, ModelElement targetRolePlayer)
{
ArtistAppearsInAlbum link = elementLink as ArtistAppearsInAlbum;
if (link != null
&& targetDomainRole.RolePlayer.Id == Album.DomainClassId)
{
// Count other unvisited links to the Album of this link.
if (ArtistAppearsInAlbum.GetLinksToArtists(link.Album)
.Where(linkAlbumArtist =>
linkAlbumArtist != link &&
!walker.Visited(linkAlbumArtist))
.Count() == 0)
{
// Should delete this role player:
return VisitorFilterResult.Yes;
}
else
// Don’t delete unless another relationship deletes it:
return VisitorFilterResult.DoNotCare;
}
else
{
// Test for and respond to other relationships and roles here.
// Not the relationship or role we’re interested in.
return base.ShouldVisitRolePlayer(walker, sourceElement,
elementLink, targetDomainRole, targetRolePlayer);
}
}
}
A técnica de fechamento garante que o conjunto de elementos e links a serem excluídos é determinado antes do início da exclusão.A walker também combina os resultados de seu encerramento com os de outras partes do modelo.
No entanto, a técnica assume que a exclusão afeta somente seus vizinhos no gráfico de relações: você não pode usar esse método para excluir um elemento em outra parte do modelo.Você não pode usá-lo se você desejar adicionar elementos ou fazer outras alterações em resposta a uma exclusão.
Usando OnDeleting e OnDeleted
Você pode substituir OnDeleting() ou OnDeleted() em uma classe de domínio, ou em uma relação de domínio.
OnDeletingé chamado quando um elemento está prestes a ser excluída, mas antes de tem sido desconectadas suas relações.Ele é ainda navegável para e de outros elementos e está ainda em store.ElementDirectory.
Se vários elementos forem excluídos ao mesmo tempo, o OnDeleting é chamado para todos eles antes de executar as exclusões.
IsDeletingé verdade.
OnDeletedé chamado quando o elemento foi excluído.Ele permanece na heap CLR para que um comando Desfazer pode ser executado, se necessário, mas é sem links de outros elementos e removido do store.ElementDirectory.Para relações, as funções ainda referencia os antiga players de função.IsDeleted is true.
OnDeleting e OnDeleted são chamados quando o usuário chama desfazer após uma criação de um elemento e uma exclusão anterior é repetida em Refazer.Use this.Store.InUndoRedoOrRollback para evitar a atualização de elementos de armazenamento nesses casos.Para obter mais informações, consulte Como: usar transações para atualizar o modelo.
Por exemplo, o código a seguir exclui um álbum quando seu último filho de música é excluído:
// Delete the parent Album when the last Song is deleted.
// Override methods in the embedding relationship between Album and Song:
partial class AlbumHasSongs
{
protected override void OnDeleted()
{
base.OnDeleted();
// Don't perform in-store actions in undo:
if (this.Store.InUndoRedoOrRollback) return;
// Relationship source and target still work:
// Don't bother if source is already on its way out:
if (!this.Album.IsDeleting && !this.Album.IsDeleted)
{
if (this.Album.Songs.Count == 0)
{
this.Album.Delete();
} } } }
Geralmente é mais útil para disparar contra a exclusão da relação que o elemento de função, como isso funciona quando o elemento é excluído, e quando o próprio relacionamento é excluído.Entretanto, para uma relação de referência, você pode querer Propagar exclusão quando um elemento relacionado é excluído, mas não quando o próprio relacionamento é excluído.Este exemplo exclui um álbum quando seu último artista Colaborador é excluída, mas ele não responder se as relações são excluídas:
using System.Linq; ...
// Assumes a many-many reference relationship
// between Artist and Album.
partial class Artist
{
protected override void OnDeleting()
{
base.OnDeleting();
if (this.Store.InUndoRedoOrRollback) return;
List<Album> toDelete = new List<Album>();
foreach (Album album in this.Albums)
{
if (album.Artists.Where(artist => !artist.IsDeleting)
.Count() == 0)
{
toDelete.Add(album);
}
}
foreach (Album album in toDelete)
{
album.Delete();
} } }
Quando você executa Delete em um elemento, OnDeleting e OnDeleted serão chamado.Esses métodos são sempre realizada in-line – ou seja, imediatamente antes e após a exclusão real.Se seu código exclui dois ou mais elementos, OnDeleting e OnDeleted serão chamado na alternância em todos eles por sua vez.
Regras de exclusão e eventos
Como alternativa para AoExcluir manipuladores, você pode definir regras de exclusão e eventos de exclusão.
Deletinge Delete as regras são acionadas somente em uma transação e não em um desfazer ou refazer.Você pode defini-las em fila para executar no final da transação na qual a exclusão é executada.Regras de exclusão são sempre executadas antes de quaisquer regras de excluídos que estão na fila.
Use regras para propagar as alterações que afetam somente os elementos no armazenamento, inclusive relações, elementos de diagrama e suas propriedades.Normalmente, uma regra de exclusão é usada para propagar a exclusão e a regra de exclusão é usada para criar relações e elementos de substituição.
Para obter mais informações, consulte Regras de propagam alterações dentro do modelo.
Deletedevento de armazenamento é chamado no final de uma transação e é chamado após um desfazer ou refazer.Portanto, pode ser usado para propagar exclusões para os objetos fora do armazenamento como, por exemplo, arquivos, entradas de banco de dados ou outros objetos na Visual Studio.
Para obter mais informações, consulte Manipuladores de eventos propagam alterações fora do modelo.
Cuidado Quando um elemento tiver sido excluído, você pode acessar seus valores de propriedade de domínio, mas não é possível navegar os links de relacionamento.No entanto, se você definir um evento excluído em um relacionamento, você também pode acessar os dois elementos que estavam seus players de função.Portanto, se você quiser responder à exclusão de um elemento de modelo, mas deseja acessar um elemento ao qual ele foi vinculado, defina um evento delete na relação em vez da classe de domínio do elemento de modelo.
Regras de exclusão de exemplo
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletingRule : DeletingRule
{
public override void ElementDeleting(ElementDeletingEventArgs e)
{
base.ElementDeleting(e);
// ...perform tasks to propagate imminent deletion
}
}
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletedRule : DeleteRule
{
public override void ElementDeleted(ElementDeletedEventArgs e)
{
base.ElementDeleted(e);
// ...perform tasks such as creating new elements
}
}
// The rule must be registered:
public partial class MusicLibDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(AlbumDeletingRule));
types.Add(typeof(AlbumDeletedRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
Evento de exemplo excluído
partial class NestedShapesSampleDocData
{
protected override void OnDocumentLoaded(EventArgs e)
{
base.OnDocumentLoaded(e);
DomainRelationshipInfo commentRelationship =
this.Store.DomainDataDirectory
.FindDomainRelationship(typeof(CommentsReferenceComponents));
this.Store.EventManagerDirectory.ElementDeleted.Add(commentRelationship,
new EventHandler<ElementDeletedEventArgs>(CommentLinkDeleted));
}
private void CommentLinkDeleted (object sender, ElementDeletedEventArgs e)
{
CommentsReferenceComponents link = e.ModelElement as CommentsReferenceComponents;
Comment comment = link.Comment;
Component component = link.Subject;
if (comment.IsDeleted)
{
// The link was deleted because the comment was deleted.
System.Windows.Forms.MessageBox.Show("Removed comment on " + component.Name);
}
else
{
// It was just the link that was deleted - the comment itself remains.
System.Windows.Forms.MessageBox.Show("Removed comment link to "
+ component.Name);
}
}
}
Desfazer a mesclagem
A operação que conecta um elemento filho ao seu pai é chamada de mesclagem.Ele ocorre quando um novo elemento ou grupo de elementos é criado a partir da caixa de ferramentas, ou movido de uma outra parte do modelo ou copiado da área de transferência.Bem como criar uma relação entre o pai e seu novo filho de incorporação, a operação de mesclagem também pode configurar relacionamentos adicionais, criar elementos auxiliares e definir valores de propriedade nos elementos.A operação de mesclagem é encapsulada em uma diretiva de mesclagem de elemento (EMD).
Um EMD encapsula o complementares também unmerge ou MergeDisconnect operação.Se você tiver um cluster de elementos que tiverem sido construído por meio de uma mala direta, é recomendável usar o associado unmerge para remover um elemento a partir dele, se você deseja deixar os elementos restantes em um estado consistente.A operação unmerge geralmente usarão as técnicas descritas nas seções anteriores.
Para obter mais informações, consulte Personalizando a movimentação e criação de elemento.
Consulte também
Conceitos
Personalizar o comportamento de cópia
Personalizando a movimentação e criação de elemento
Outros recursos
Escrever código para personalizar uma linguagem específica de domínio