Esplorazione e aggiornamento di un modello nel codice del programma
È possibile scrivere codice per creare ed eliminare elementi del modello, impostare le proprietà e per creare ed eliminare collegamenti tra elementi.Tutte le modifiche devono essere apportate all'interno di una transazione.Se gli elementi vengono visualizzati in un diagramma, il diagramma “verrà corretto in„ automaticamente alla fine della transazione.
In questo argomento
Una definizione di modello DSL di esempio
esplorare il modello
Per accedere alle informazioni sulle classi
Eseguire modifiche in una transazione
Creare elementi del modello
Creare collegamenti di relazione
eliminare gli elementi
Eliminare collegamenti di relazione
riordinare i collegamenti di una relazione
blocchi
Copiare e incollare
Spostamento e aggiornamento dei diagrammi
Spostamento fra le forme e gli elementi
Proprietà delle forme e i connettori
DocView e DocData
Le forme, connettori e i diagrammi e le relative relazioni agli elementi del modello vengono descritti in un argomento distinto.Per ulteriori informazioni, vedere [reindirizzamento] Procedura: esplorare e aggiornare un diagramma.
Una definizione di modello DSL di esempio
Si tratta della parte principale di DslDefinition.dsl per gli esempi di questo argomento:
Questo modello è un'istanza di questo modello DSL:
Riferimenti e spazi dei nomi
Per eseguire il codice in questo argomento, è necessario fare riferimento a:
Microsoft.VisualStudio.Modeling.Sdk.11.0.dll
Il codice utilizzerà questo spazio dei nomi:
using Microsoft.VisualStudio.Modeling;
Inoltre, se si scrive codice in un progetto diverso da quello in cui il modello DSL è definito, è necessario includere l'assembly compilato dal progetto di Dsl.
esplorare il modello
Proprietà
Le proprietà del dominio specificato nella definizione di modello DSL divengono proprietà che è possibile accedere nel codice programma:
Person henry = ...;
if (henry.BirthDate < 1500) ...
if (henry.Name.EndsWith("VIII")) ...
Se si desidera impostare una proprietà, è necessario farlo in un oggetto transazione:
henry.Name = "Henry VIII";
Se nella definizione di modello DSL, una proprietà tipo viene calcolato, non è possibile impostarlo.Per ulteriori informazioni, vedere Proprietà di archiviazione calcolate e personalizzate.
Relazioni
Relazioni di dominio definite nella definizione di modello DSL diventano le coppie delle proprietà, una sulla classe a ogni estremità della relazione.I nomi delle proprietà vengono visualizzate nel diagramma di DslDefinition come etichette sui ruoli su ciascun lato della relazione.A seconda della molteplicità del ruolo, il tipo della proprietà è la classe all'altra estremità della relazione, o una raccolta della classe.
foreach (Person child in henry.Children) { ... }
FamilyTreeModel ftree = henry.FamilyTreeModel;
Proprietà a estremi opposti di una relazione sono sempre mutex.Quando un collegamento viene creato o eliminato, il ruolo delle proprietà in entrambi gli elementi viene aggiornato.La seguente espressione (in cui le estensioni System.Linq) è sempre true per la relazione di ParentsHaveChildren nell'esempio:
(Person p) => p.Children.All(child => child.Parents.Contains(p))
&& p.Parents.All(parent => parent.Children.Contains(p));
ElementLinks.Una relazione viene rappresentata da un elemento del modello chiamata a collegamento, che rappresenta un'istanza del tipo di relazione di dominio.Un collegamento è sempre un elemento di origine e un elemento di destinazione.L'elemento di origine e l'elemento di destinazione possono corrispondere.
È possibile accedere a un collegamento e le relative proprietà:
ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);
// This is now true:
link == null || link.Parent == henry && link.Child == edward
Per impostazione predefinita, a non più di un'istanza di una relazione è consentita per collegare qualsiasi coppia di elementi del modello.Ma se nella definizione di modello DSL, Allow Duplicates il flag è true per la relazione, quindi è possibile che più di un collegamento ed è necessario utilizzare GetLinks:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }
Esistono anche altri metodi per l'accesso ai collegamenti.Di seguito è riportato un esempio:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }
ruoli nascosti. Se nella definizione di modello DSL, è la proprietà generata viene false per un particolare ruolo, quindi la proprietà non viene generata corrispondente al ruolo.Tuttavia, è ancora possibile accedere ai collegamenti e scorrere i collegamenti utilizzando i metodi della relazione:
foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }
Il più delle volte viene utilizzato PresentationViewsSubject relazione, che collega un elemento del modello sulla forma che visualizza in un diagramma:
PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape
La directory dell'elemento
È possibile accedere a tutti gli elementi nell'archivio utilizzando la directory dell'elemento:
store.ElementDirectory.AllElements
Esistono anche metodi per trovare gli elementi, quali:
store.ElementDirectory.FindElements(Person.DomainClassId);
store.ElementDirectory.GetElement(elementId);
Per accedere alle informazioni sulle classi
È possibile ottenere informazioni sulle classi, le relazioni e altri aspetti della definizione di modello DSL.Di seguito è riportato un esempio:
DomainClassInfo personClass = henry.GetDomainClass();
DomainPropertyInfo birthProperty =
personClass.FindDomainProperty("BirthDate")
DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];
Le classi predecessore di elementi del modello sono le seguenti:
ModelElement - tutti gli elementi e relazioni sono ModelElements
ElementLink - tutte le relazioni vengono ElementLinks
Eseguire modifiche in una transazione
Ogni volta che il codice del programma modifica qualsiasi elemento nell'archivio, è necessario farlo in una transazione.Ciò vale per tutti gli elementi del modello, le relazioni, le forme, ai diagrammi e alle relative proprietà.Per ulteriori informazioni, vedere Transaction.
Il metodo più pratico di gestire una transazione è con un oggetto using istruzione allegato a l try...catch istruzione:
Store store; ...
try
{
using (Transaction transaction =
store.TransactionManager.BeginTransaction("update model"))
// Outermost transaction must always have a name.
{
// Make several changes in Store:
Person p = new Person(store);
p.FamilyTreeModel = familyTree;
p.Name = "Edward VI";
// end of changes to Store
transaction.Commit(); // Don't forget this!
} // transaction disposed here
}
catch (Exception ex)
{
// If an exception occurs, the Store will be
// rolled back to its previous state.
}
È possibile eseguire qualsiasi numero di modifiche in una transazione.È possibile aprire le nuove transazioni in una transazione attiva.
Per rendere modifiche permanenti, è necessario Commit la transazione prima che venga eliminato.Se si verifica un'eccezione che non viene intercettata nella transazione, quest'ultimo verrà reimpostato allo stato precedente le modifiche.
Creare elementi del modello
In questo esempio viene aggiunto un elemento a un modello esistente:
FamilyTreeModel familyTree = ...; // The root of the model.
using (Transaction t =
familyTree.Store.TransactionManager
.BeginTransaction("update model"))
{
// Create a new model element
// in the same partition as the model root:
Person edward = new Person(familyTree.Partition);
// Set its embedding relationship:
edward.FamilyTreeModel = familyTree;
// same as: familyTree.People.Add(edward);
// Set its properties:
edward.Name = "Edward VII";
t.Commit(); // Don't forget this!
}
In questo esempio vengono illustrati questi punti relativi alla creazione di un elemento:
Creare il nuovo elemento in una partizione specifica dell'archivio.Per gli elementi del modello e le relazioni, ma non le forme, questa viene in genere la partizione predefinita.
Selezionarla nella destinazione di una relazione che utilizza.In DslDefinition di questo esempio, ogni persona deve essere la destinazione di incorporare la relazione FamilyTreeHasPeople.A tale scopo, è possibile o impostare la proprietà di FamilyTreeModel il ruolo dell'oggetto person, aggiungere la persona la proprietà degli utenti al ruolo dell'oggetto di FamilyTreeModel.
Impostare le proprietà del nuovo elemento, in particolare la proprietà per il quale IsName è true nel DslDefinition.Questo flag contrassegna la proprietà che consente di identificare l'elemento in modo univoco all'interno del proprietario.In questo caso, la proprietà name con il flag.
La definizione di modello DSL di questo modello DSL deve essere caricata nell'archivio.Se si scrive un'estensione quale un comando di menu, in genere è già true.In altri casi, è possibile creare in modo esplicito caricare il modello nell'archivio, o utilizzo ModelBus per caricarla.Per ulteriori informazioni, vedere Procedura: aprire un modello da file nel codice del programma.
Quando si crea un elemento in questo modo, una forma viene creata automaticamente (se il modello DSL dispone di un diagramma).Viene visualizzato in una posizione automaticamente assegnata, con forma predefinita, colore e altre funzionalità.Se si desidera controllare dove la forma associata viene visualizzato, vedere Creare un elemento e la relativa forma.
Creare collegamenti di relazione
Esistono due relazioni definite nella definizione di modello DSL di esempio.Ogni relazione definito un oggetto ruolo della proprietà nella classe a ogni estremità della relazione.
Esistono tre modi in cui è possibile creare un'istanza di una relazione.Ognuno di questi tre metodi ha lo stesso effetto:
Impostare la proprietà del ruolo di origine di giocatore.Di seguito è riportato un esempio:
familyTree.People.Add(edward);
edward.Parents.Add(henry);
Impostare la proprietà del ruolo di destinazione di giocatore.Di seguito è riportato un esempio:
edward.familyTreeModel = familyTree;
la molteplicità di questo ruolo è 1..1pertanto, assegniamo il valore.
henry.Children.Add(edward);
la molteplicità di questo ruolo è 0..*, pertanto viene aggiunto alla raccolta.
Costruisce un'istanza con relazione in modo esplicito.Di seguito è riportato un esempio:
FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);
ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);
L'ultimo metodo è utile per impostare le proprietà della relazione stessa.
Quando si crea un elemento in questo modo, un connettore nel diagramma viene creato automaticamente, ma dispone di una forma predefinita, il colore e altre funzionalità.Per controllare come il connettore associato viene creato, vedere Creare un elemento e la relativa forma.
eliminare gli elementi
Rimuovere un elemento chiamando Delete():
henry.Delete();
Questa operazione viene eliminata:
Collegamenti di relazione da e verso l'elemento.Ad esempio, edward.Parents in non conterrà henry.
Elementi ai ruoli per cui PropagatesDelete il flag è true.Ad esempio, la forma che visualizza l'elemento viene eliminato.
Per impostazione predefinita, ogni relazione che utilizza ha PropagatesDelete allineare al ruolo di destinazione.eliminare henry non elimina familyTreetuttavia, familyTree.Delete() eliminerebbe qualsiasi Persons.Per ulteriori informazioni, vedere Personalizzazione del comportamento di eliminazione.
per impostazione predefinita, PropagatesDelete non vale per i ruoli delle relazioni di riferimento.
È possibile determinare le regole di eliminazione omettere le propagazioni specifiche quando si elimina un oggetto.Ciò si rivela utile se si sta sostituendo un elemento a un altro.Fornire il GUID di uno o più ruoli per il quale di eliminazione non dovranno essere propagati.Il GUID può essere ottenuto dalla classe di relazioni:
henry.Delete(ParentsHaveChildren.SourceDomainRoleId);
In questo particolare esempio non avrebbe alcun effetto, poiché PropagatesDelete viene false per i ruoli di ParentsHaveChildren relazione.)
In alcuni casi, l'eliminazione viene impedita dall'esistenza di un blocco, sull'elemento o un elemento che verrebbe eliminato dalla propagazione.È possibile utilizzare element.CanDelete() per controllare se l'elemento possa essere eliminati.
Eliminare collegamenti di relazione
È possibile eliminare un collegamento di relazione rimuovere un elemento da un ruolo della proprietà:
henry.Children.Remove(edward); // or:
edward.Parents.Remove(henry); // or:
È inoltre possibile eliminare il collegamento esplicito:
edwardHenryLink.Delete();
Questi tre metodi sono tutti dello stesso effetto.È sufficiente utilizzare una di esse.
Se il ruolo dispone di 0..1 o 1..1 molteplicità, è possibile impostarlo su null, o a un altro valore:
edward.FamilyTreeModel = null; //o:
edward.FamilyTreeModel = anotherFamilyTree;
Riordinazione dei collegamenti di una relazione
I collegamenti di una particolare relazione che sono originati o indirizzati a un elemento del modello specifico hanno una sequenza specifica.Vengono visualizzate nell'ordine in cui sono stati aggiunti.Ad esempio, questa istruzione sarà sempre gli elementi figlio nello stesso ordine:
foreach (Person child in henry.Children) ...
È possibile modificare l'ordine dei collegamenti:
ParentsHaveChildren link = GetLink(henry,edward);
ParentsHaveChildren nextLink = GetLink(henry, elizabeth);
DomainRoleInfo role =
link.GetDomainRelationship().DomainRoles[0];
link.MoveBefore(role, nextLink);
blocchi
Le modifiche possono essere si impedisce da un blocco.I blocchi possono essere impostati i singoli elementi, sulle partizioni e riguardanti l'archivio.Se uno di questi livelli dispone di un blocco che impedisce il tipo di modifica da apportare, viene generata un'eccezione può essere generata quando la si tenta.È possibile verificare che i blocchi vengono impostati tramite l'elemento. GetLocks(), che è un metodo di estensione definito in Immutability.
Per ulteriori informazioni, vedere Definizione di un criterio di blocco per creare segmenti di sola lettura.
Copiare e incollare
È possibile copiare elementi o gruppi di elementi a un oggetto IDataObject:
Person person = personShape.ModelElement as Person;
Person adopter = adopterShape.ModelElement as Person;
IDataObject data = new DataObject();
personShape.Diagram.ElementOperations
.Copy(data, person.Children.ToList<ModelElement>());
Gli elementi vengono archiviati come gruppo serializzato dell'elemento.
È possibile unire elementi da un IDataObject in un modello:
using (Transaction t = targetDiagram.Store.
TransactionManager.BeginTransaction("paste"))
{
adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}
Merge () può accettare o un oggetto PresentationElement oppure ModelElement.Se è necessario assegnargli un oggetto PresentationElement, è anche possibile specificare una posizione nel diagramma di destinazione come terzo parametro.
Spostamento e aggiornamento dei diagrammi
In un modello DSL, l'elemento del modello di dominio, che rappresenta un concetto come la persona o canzone, è distinta dall'elemento di formato, che rappresenta gli elementi visualizzati nel diagramma.L'elemento del modello di dominio archivia le proprietà e le relazioni principali concetti.L'elemento della forma archivia la dimensione, posizione e il colore della visualizzazione dell'oggetto nel diagramma e il layout degli elementi.
elementi di presentazione
Nella definizione di modello DSL, ogni elemento specificato crea una classe che deriva da una delle classi standard.
tipo di elemento |
Classe base |
---|---|
classe di dominio |
|
relazione di dominio |
|
Forma |
|
connettore |
|
Diagramma |
Un elemento in un diagramma in genere rappresenta un elemento del modello.Solitamente ma non sempre), a NodeShape rappresenta un'istanza della classe di dominio e un oggetto BinaryLinkShape rappresenta un'istanza di relazione di dominio.PresentationViewsSubject la relazione collega una forma di collegamento o del nodo all'elemento del modello che rappresenta.
Ogni forma di collegamento o del nodo appartiene a un diagramma.Una forma binaria di collegamento connette due forme del nodo.
Le forme possono avere forme figlio in due set.una forma in NestedChildShapes l'insieme è limitato al riquadro delimitatore del padre.una forma in RelativeChildShapes l'elenco può essere attiva o parzialmente oltre i limiti del padre ad esempio un'etichetta o una porta.Un diagramma dispone di alcun RelativeChildShapes oppure no Parent.
Spostamento fra le forme e gli elementi
Gli elementi del modello di dominio e gli elementi di formato sono correlati da PresentationViewsSubject relazione.
// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape =
PresentationViewsSubject.GetPresentation(henry)
.FirstOrDefault() as PersonShape;
La stessa relazione correla le relazioni ai connettori nel diagramma:
Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
PresentationViewsSubject.GetPresentation(link)
.FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape
Questa relazione viene collega la radice del modello nel diagramma:
FamilyTreeDiagram diagram =
PresentationViewsSubject.GetPresentation(familyTree)
.FirstOrDefault() as FamilyTreeDiagram;
Per ottenere l'elemento del modello rappresentato da una forma, utilizzare:
henryShape.ModelElement as Person
diagram.ModelElement as FamilyTreeModel
Spostamento al diagramma
In generale non è consigliabile utilizzare spostarsi tra le forme e i connettori nel diagramma.È preferibile esplorare le relazioni nel modello, il passaggio tra le forme e i connettori solo quando è necessario lavorare sull'aspetto del diagramma.Questi metodi collega i connettori alle forme a ogni estremità:
personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes
connector.FromShape, connector.ToShape
Molte forme vengono composti, sono costituiti da una forma padre e uno o più livelli di elementi figlio.Forme che l'oggetto è posizionato in relazione a un'altra forma sarebbe relativo figlio.Quando la forma padre viene spostato, move figlio con.
Figlio correlati può apparire all'esterno del riquadro delimitatore della forma padre.Annidato gli elementi figlio vengono visualizzati soltanto nei limiti.
Per ottenere il set superiore di forme su un diagramma, utilizzare:
Diagram.NestedChildShapes
le classi predecessore di forme e di connettori sono:
-- ShapeElement
----- NodeShape
------- Diagram
------- TheShape
----- LinkShape
------- BinaryLinkShape
--------- TheConnector
Proprietà delle forme e i connettori
Nella maggior parte dei casi, non è necessario apportare modifiche esplicite alle forme.Dopo avere modificato gli elementi del modello, “correggere su„ regole aggiornano le forme e i connettori.Per ulteriori informazioni, vedere Risposta alle modifiche e propagazione delle modifiche.
Tuttavia, è utile apportare alcune modifiche esplicite alle forme nelle proprietà che sono indipendenti dagli elementi del modello.Ad esempio, è possibile modificare queste proprietà:
Size - consente di determinare l'altezza e la larghezza della forma.
Location - inserire relativo alla forma o il diagramma padre
StyleSet ovvero l'insieme di autori e di pennelli utilizzato per disegnare una forma o il connettore
Hide - rende la forma invisibile
Show - rende la forma visibile dopo un oggetto Hide()
Creare un elemento e la relativa forma
Quando si crea un elemento e importarlo nella struttura ad albero di incorporare le relazioni, una forma viene automaticamente creata e associata.Questa operazione viene eseguita da “correzioni„ regole che di esecuzione alla fine della transazione.Tuttavia, la forma verrà visualizzato in una posizione automaticamente-assegnata e la relativa forma, il colore e altre funzionalità conserveranno valori predefiniti.Per controllare come la forma creata, è possibile utilizzare la funzione di unione.Aggiungere innanzitutto gli elementi che si desidera aggiungere in un ElementGroup quindi unisce il gruppo nel diagramma.
Il metodo:
Imposta il nome, se è stata assegnata una proprietà come nome dell'elemento.
Vengono rispettate le direttive di unione dell'elemento specificato nella definizione di modello DSL.
In questo esempio viene creata una forma alla posizione del mouse, quando l'utente fa doppio clic sul diagramma.Nella definizione di modello DSL per questo esempio, FillColor proprietà di ExampleShape è stato esposto.
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
partial class MyDiagram
{
public override void OnDoubleClick(DiagramPointEventArgs e)
{
base.OnDoubleClick(e);
using (Transaction t = this.Store.TransactionManager
.BeginTransaction("double click"))
{
ExampleElement element = new ExampleElement(this.Store);
ElementGroup group = new ElementGroup(element);
{ // To use a shape of a default size and color, omit this block.
ExampleShape shape = new ExampleShape(this.Partition);
shape.ModelElement = element;
shape.AbsoluteBounds = new RectangleD(0, 0, 1.5, 1.0);
shape.FillColor = System.Drawing.Color.Azure;
group.Add(shape);
}
this.ElementOperations.MergeElementGroupPrototype(
this,
group.CreatePrototype(),
PointD.ToPointF(e.MousePosition));
t.Commit();
}
}
}
Se si specifica più di un form, impostare le relative posizioni relative mediante AbsoluteBounds.
È anche possibile impostare il colore e altre proprietà esposte dei connettori utilizzando questo metodo.
transazioni di utilizzo
Le forme, connettori e i diagrammi sono sottotipi di ModelElement e avvenire nell'archivio.È necessario quindi apportare le modifiche solo in una transazione.Per ulteriori informazioni, vedere Procedura: utilizzare le transazioni per aggiornare il modello.
Documento di visualizzazione e i dati del documento
Partizioni dell'archivio
Quando viene caricato un modello, il diagramma associato viene caricato contemporaneamente.In genere, il modello viene caricato in Store.DefaultPartition e il contenuto del diagramma viene caricato in un'altra partizione.In genere, il contenuto di ogni partizione viene caricato e salvato in un file separato.
Vedere anche
Riferimenti
Concetti
Convalida in un linguaggio specifico di dominio
Procedura: utilizzare le transazioni per aggiornare il modello
Integrazione di modelli tramite ModelBus di Visual Studio