Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat menulis kode untuk membuat dan menghapus elemen model, mengatur propertinya, serta membuat dan menghapus link antar elemen. Semua perubahan harus dilakukan dalam transaksi. Jika elemen ditampilkan pada diagram, diagram akan “diperbaiki” secara otomatis di akhir transaksi.
Contoh Definisi Bahasa Khusus Domain
Ini adalah bagian utama dari DslDefinition.dsl untuk contoh dalam topik ini:
Model ini adalah instans bahasa khusus domain ini:
Referensi dan Namespace Layanan
Untuk menjalankan kode dalam topik ini, Anda harus mereferensikan:
Microsoft.VisualStudio.Modeling.Sdk.11.0.dll
Kode Anda akan menggunakan namespace layanan ini:
using Microsoft.VisualStudio.Modeling;
Selain itu, jika Anda menulis kode dalam proyek yang berbeda dari yang didefinisikan bahasa khusus domain Anda, Anda harus mengimpor rakitan yang dibangun oleh proyek Dsl.
Menavigasi Model
Properti
Properti domain yang Anda tentukan dalam definisi bahasa khusus domain menjadi properti yang dapat Anda akses dalam kode program:
Person henry = ...;
if (henry.BirthDate < 1500) ...
if (henry.Name.EndsWith("VIII")) ...
Jika Anda ingin mengatur properti, Anda harus melakukannya di dalam transaksi:
henry.Name = "Henry VIII";
Jika dalam definisi bahasa khusus domain, Jenis properti Dihitung, Anda tidak dapat mengaturnya. Untuk informasi selengkapnya, lihat Properti Penyimpanan Terhitung dan Kustom.
Hubungan
Hubungan domain yang Anda tentukan dalam definisi bahasa khusus domain menjadi pasangan properti, satu pada kelas di setiap akhir hubungan. Nama properti muncul dalam diagram DslDefinition sebagai label pada peran di setiap sisi hubungan. Bergantung pada kardinalitas peran, jenis properti adalah kelas di akhir hubungan lainnya, atau kumpulan kelas tersebut.
foreach (Person child in henry.Children) { ... }
FamilyTreeModel ftree = henry.FamilyTreeModel;
Properti di akhir hubungan yang berlawanan selalu bersifat timbal balik. Ketika link dibuat atau dihapus, properti peran pada kedua elemen diperbarui. Ekspresi berikut (yang menggunakan ekstensi System.Linq
) selalu benar untuk hubungan ParentsHaveChildren dalam contoh:
(Person p) => p.Children.All(child => child.Parents.Contains(p))
&& p.Parents.All(parent => parent.Children.Contains(p));
ElementLinks. Hubungan juga diwakili oleh elemen model yang disebut link, yang merupakan instans jenis hubungan domain. Link selalu memiliki satu elemen sumber dan satu elemen target. Elemen sumber dan elemen target bisa sama.
Anda dapat mengakses link dan propertinya:
ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);
// This is now true:
link == null || link.Parent == henry && link.Child == edward
Secara default, tidak lebih dari satu instans hubungan diizinkan untuk menautkan sepasang elemen model. Namun, jika dalam definisi DSL, bendera Allow Duplicates
benar untuk hubungan, maka mungkin ada lebih dari satu link, dan Anda harus menggunakan GetLinks
:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }
Ada juga metode lain untuk mengakses link. Misalnya:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }
Peran tersembunyi. Jika dalam definisi DSL, Apakah Properti Yang Dihasilkan adalah false untuk peran tertentu, maka tidak ada properti yang dihasilkan yang sesuai dengan peran tersebut. Namun, Anda masih dapat mengakses link dan melintasi link menggunakan metode hubungan:
foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }
Contoh yang paling sering digunakan adalah hubungan PresentationViewsSubject, yang menautkan elemen model ke bentuk yang menampilkannya pada diagram:
PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape
Direktori Elemen
Anda dapat mengakses semua elemen di penyimpanan menggunakan direktori elemen:
store.ElementDirectory.AllElements
Ada juga metode untuk menemukan elemen, seperti sebagai berikut:
store.ElementDirectory.FindElements(Person.DomainClassId);
store.ElementDirectory.GetElement(elementId);
Mengakses Informasi Kelas
Anda bisa mendapatkan informasi tentang kelas, hubungan, dan aspek lain dari definisi DSL. Misalnya:
DomainClassInfo personClass = henry.GetDomainClass();
DomainPropertyInfo birthProperty =
personClass.FindDomainProperty("BirthDate")
DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];
Kelas leluhur elemen model adalah sebagai berikut:
ModelElement - semua elemen dan hubungan adalah ModelElements
ElementLink - semua hubungan adalah ElementLinks
Melakukan Perubahan di dalam Transaksi
Setiap kali kode program Anda mengubah apa pun di Store, kode tersebut harus dilakukan di dalam transaksi. Kode ini berlaku untuk semua elemen model, hubungan, bentuk, diagram, dan propertinya. Untuk informasi selengkapnya, lihat Transaction .
Metode paling nyaman untuk mengelola transaksi adalah dengan pernyataan using
yang diapit dalam pernyataan try...catch
:
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.
}
Anda dapat membuat sejumlah perubahan di dalam satu transaksi. Anda dapat membuka transaksi baru di dalam transaksi aktif.
Untuk membuat perubahan permanen, Anda harus Commit
melakukan transaksi sebelum dibuang. Jika terjadi pengecualian yang tidak tertangkap di dalam transaksi, Store akan diatur ulang ke statusnya sebelum perubahan.
Membuat Elemen Model
Contoh ini menambahkan elemen ke model yang sudah ada:
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!
}
Contoh ini mengilustrasikan poin-poin penting ini tentang membuat elemen:
Buat elemen baru dalam partisi tertentu dari Store. Untuk elemen dan hubungan model, tetapi bukan bentuk, ini biasanya merupakan partisi default.
Jadikan target hubungan penyematan. Dalam DslDefinition contoh ini, setiap Orang harus menjadi target hubungan penyematan FamilyTreeHasPeople. Untuk mencapai hal ini, kita dapat mengatur properti peran FamilyTreeModel dari objek Orang, atau menambahkan Orang ke properti peran Manusia dari objek FamilyTreeModel.
Atur properti elemen baru, terutama properti yang
IsName
adalah true di DslDefinition. Bendera ini menandai properti yang berfungsi untuk mengidentifikasi elemen secara unik dalam pemiliknya. Dalam hal ini, properti Nama memiliki bendera tersebut.Definisi bahasa khusus domain dari bahasa khusus domain ini harus telah dimuat ke dalam Store. Jika Anda menulis ekstensi seperti perintah menu, ini biasanya sudah true. Dalam kasus lain, Anda dapat secara eksplisit memuat model ke Store, atau menggunakan ModelBus untuk memuatnya. Untuk mendapatkan informasi selengkapnya, lihat Cara: Membuka Model dari File dalam Kode Program.
Ketika Anda membuat elemen dengan cara ini, bentuk secara otomatis dibuat (jika bahasa khusus domain memiliki diagram). Bentuk ini muncul di lokasi yang ditetapkan secara otomatis, dengan bentuk, warna, dan fitur default lainnya. Jika Anda ingin mengontrol tempat dan cara bentuk terkait muncul, lihat Membuat Elemen dan Bentuknya.
Membuat Link Hubungan
Ada dua hubungan yang ditentukan dalam contoh definisi bahasa khusus domain. Setiap hubungan mendefinisikan properti peran pada kelas di setiap akhir hubungan.
Ada tiga cara tempat Anda dapat membuat instans hubungan. Masing-masing dari ketiga metode ini memiliki efek yang sama:
Atur properti pemutar peran sumber. Misalnya:
familyTree.People.Add(edward);
edward.Parents.Add(henry);
Atur properti pemutar peran target. Misalnya:
edward.familyTreeModel = familyTree;
Kardinalitas peran ini adalah
1..1
, sehingga kami menetapkan nilainya.henry.Children.Add(edward);
Kardinalitas peran ini adalah
0..*
, sehingga kami menambahkan ke koleksi.
Buat instans hubungan secara eksplisit. Misalnya:
FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);
ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);
Metode terakhir berguna jika Anda ingin mengatur properti pada hubungan itu sendiri.
Ketika Anda membuat elemen dengan cara ini, konektor pada diagram dibuat secara otomatis, tetapi memiliki bentuk, warna, dan fitur default lainnya. Untuk mengontrol cara konektor terkait dibuat, lihat Membuat Elemen dan Bentuknya.
Menghapus Elemen
Hapus elemen dengan memanggil Delete()
:
henry.Delete();
Operasi ini juga akan menghapus:
Link hubungan ke dan dari elemen. Contohnya,
edward.Parents
tidak akan lagi memuathenry
.Elemen pada peran yang bendera
PropagatesDelete
adalah true. Contohnya, bentuk yang menampilkan elemen akan dihapus.
Secara default, setiap hubungan penyematan memiliki PropagatesDelete
true pada peran target. Menghapus henry
tidak menghapus familyTree
, tetapi familyTree.Delete()
akan menghapus semua Persons
.
Secara default, PropagatesDelete
bukan true untuk peran hubungan referensi.
Anda dapat menyebabkan aturan penghapusan untuk menghilangkan penyebarluasan tertentu ketika Anda menghapus objek. Aturan ini berguna jika Anda mengganti satu elemen dengan elemen lain. Anda menyediakan GUID dari satu atau beberapa peran yang penghapusannya tidak boleh disebarluaskan. GUID dapat diperoleh dari kelas hubungan:
henry.Delete(ParentsHaveChildren.SourceDomainRoleId);
(Contoh khusus ini tidak akan berpengaruh, karena PropagatesDelete
adalah false
untuk peran hubungan ParentsHaveChildren
.)
Dalam beberapa kasus, penghapusan dicegah oleh keberadaan kunci, baik pada elemen maupun pada elemen yang akan dihapus oleh penyebarluasan. Anda dapat menggunakan element.CanDelete()
untuk memeriksa apakah elemen dapat dihapus.
Menghapus Link Hubungan
Anda dapat menghapus link hubungan dengan menghapus elemen dari properti peran:
henry.Children.Remove(edward); // or:
edward.Parents.Remove(henry); // or:
Anda juga dapat menghapus link secara eksplisit:
edwardHenryLink.Delete();
Ketiga metode ini semuanya memiliki efek yang sama. Anda hanya perlu menggunakan salah satu metode.
Jika peran memiliki kardinalitas 0..1 atau 1..1, Anda dapat mengaturnya ke null
, atau ke nilai lain:
edward.FamilyTreeModel = null;
// atau:
edward.FamilyTreeModel = anotherFamilyTree;
Mengurutkan ulang Link Hubungan
Link hubungan tertentu yang bersumber atau ditargetkan pada elemen model tertentu memiliki urutan tertentu. Link tersebut muncul dalam urutan penambahannya. Contohnya, pernyataan ini akan selalu menangguhkan turunan dalam urutan yang sama:
foreach (Person child in henry.Children) ...
Anda dapat mengubah urutan link:
ParentsHaveChildren link = GetLink(henry,edward);
ParentsHaveChildren nextLink = GetLink(henry, elizabeth);
DomainRoleInfo role =
link.GetDomainRelationship().DomainRoles[0];
link.MoveBefore(role, nextLink);
Penguncian
Perubahan Anda dapat dicegah oleh kunci. Kunci dapat diatur pada masing-masing elemen, pada partisi, dan pada penyimpanan. Jika salah satu tingkat ini memiliki kunci yang mencegah jenis perubahan yang ingin Anda lakukan, pengecualian dapat dilemparkan ketika Anda mencobanya. Anda dapat menemukan apakah kunci diatur dengan menggunakan element.GetLocks(), yang merupakan metode ekstensi yang ditentukan dalam namespace layanan Microsoft.VisualStudio.Modeling.Immutability.
Untuk mendapatkan informasi selengkapnya, lihat Menentukan Kebijakan Penguncian untuk Membuat Segmen Baca-Saja.
Salin dan Tempel
Anda dapat menyalin elemen atau grup elemen ke 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>());
Elemen disimpan sebagai Grup Elemen berseri.
Anda dapat menggabungkan elemen dari IDataObject ke dalam model:
using (Transaction t = targetDiagram.Store.
TransactionManager.BeginTransaction("paste"))
{
adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}
Merge ()
dapat menerima PresentationElement
atau ModelElement
. Jika Anda memberinya PresentationElement
, Anda juga dapat menentukan posisi pada diagram target sebagai parameter ketiga.
Menavigasi dan memperbarui diagram
Dalam bahasa khusus domain, elemen model domain, yang mewakili konsep seperti Orang atau Lagu, terpisah dari elemen bentuk, yang mewakili yang Anda lihat pada diagram. Elemen model domain menyimpan properti dan hubungan penting dari konsep. Elemen bentuk menyimpan ukuran, posisi, dan warna tampilan objek pada diagram, dan tata letak bagian komponennya.
Elemen Presentasi
Dalam Definisi Bahasa Khusus Domain Anda, setiap elemen yang Anda tentukan membuat kelas yang berasal dari salah satu kelas standar berikut.
Jenis elemen | Kelas dasar |
---|---|
Kelas domain | ModelElement |
Hubungan domain | ElementLink |
Bentuk | NodeShape |
Konektor | BinaryLinkShape |
Diagram | Diagram |
Elemen pada diagram biasanya mewakili elemen model. Biasanya (tetapi tidak selalu), NodeShape mewakili instans kelas domain, dan BinaryLinkShape mewakili instans hubungan domain. Hubungan PresentationViewsSubject ini menautkan simpul atau menautkan bentuk ke elemen model yang diwakilinya.
Setiap simpul atau bentuk link milik satu diagram. Bentuk link biner menyambungkan dua bentuk simpul.
Bentuk dapat memiliki bentuk turunan dalam dua kumpulan. Bentuk dalam kumpulan NestedChildShapes
terbatas pada kotak pembatas induknya. Bentuk dalam daftar RelativeChildShapes
dapat muncul di luar atau sebagian di luar batas induk - contohnya label atau port. Diagram tidak memiliki RelativeChildShapes
dan tidak Parent
.
Menavigasi antara bentuk dan elemen
Elemen model domain dan elemen bentuk terkait dengan hubungan PresentationViewsSubject.
// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape =
PresentationViewsSubject.GetPresentation(henry)
.FirstOrDefault() as PersonShape;
Hubungan yang sama menautkan hubungan ke konektor pada diagram:
Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
PresentationViewsSubject.GetPresentation(link)
.FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape
Hubungan ini juga menautkan akar model ke diagram:
FamilyTreeDiagram diagram =
PresentationViewsSubject.GetPresentation(familyTree)
.FirstOrDefault() as FamilyTreeDiagram;
Untuk mendapatkan elemen model yang diwakili oleh bentuk, gunakan:
henryShape.ModelElement as Person
diagram.ModelElement as FamilyTreeModel
Menavigasi di sekitar Diagram
Secara umum tidak disarankan untuk menavigasi antara bentuk dan konektor pada diagram. Lebih baik menavigasi hubungan dalam model, bergerak di antara bentuk dan konektor hanya ketika perlu untuk bekerja pada tampilan diagram. Metode ini menautkan konektor ke bentuk di setiap ujungnya:
personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes
connector.FromShape, connector.ToShape
Banyak bentuk berupa komposit; terdiri atas bentuk induk dan satu atau beberapa lapisan turunan. Bentuk yang diposisikan relatif terhadap bentuk lain dikatakan sebagai turunan. Ketika bentuk induk bergerak, turunan berpindah bersamanya.
Turunan relatif dapat muncul di luar kotak pembatas bentuk induk. Turunan bersarang muncul secara ketat di dalam batas induk.
Untuk mendapatkan kumpulan bentuk atas pada diagram, gunakan:
Diagram.NestedChildShapes
Kelas leluhur bentuk dan konektor adalah:
-- ShapeElement
----- NodeShape
------- Diagram
------- YourShape
----- LinkShape
------- BinaryLinkShape
--------- YourConnector
Properti Bentuk dan Konektor
Dalam kebanyakan kasus, tidak perlu melakukan perubahan eksplisit pada bentuk. Ketika Anda telah mengubah elemen model, aturan “perbaiki” memperbarui bentuk dan konektor. Untuk mendapatkan informasi selengkapnya, lihat Merespons dan Menyebarluaskan Perubahan.
Namun, berguna untuk melakukan beberapa perubahan eksplisit pada bentuk dalam properti yang independen dari elemen model. Contohnya, Anda dapat mengubah properti-properti ini:
Size - menentukan tinggi dan lebar bentuk.
Location - posisi relatif terhadap bentuk atau diagram induk
StyleSet - kumpulan pena dan kuas yang digunakan untuk menggambar bentuk atau konektor
Hide - membuat bentuk tidak terlihat
Show - membuat bentuk terlihat setelah
Hide()
Membuat Elemen dan Bentuknya
Ketika Anda membuat elemen dan menautkannya ke pohon hubungan penyematan, bentuk secara otomatis dibuat dan dikaitkan dengannya. Hal ini dilakukan melalui aturan “perbaikan” yang dijalankan pada akhir transaksi. Namun, bentuk akan muncul di lokasi yang ditetapkan secara otomatis, dan bentuk, warna, dan fitur lainnya akan memiliki nilai default. Untuk mengontrol cara bentuk dibuat, Anda dapat menggunakan fungsi penggabungan. Anda harus terlebih dahulu menambahkan elemen yang ingin Anda tambahkan ke dalam ElementGroup, lalu menggabungkan grup ke dalam diagram.
Metode ini:
Mengatur nama, jika Anda telah menetapkan properti sebagai nama elemen.
Mengamati Arahan Gabungan Elemen apa pun yang Anda tentukan dalam Definisi Bahasa Khusus Domain.
Contoh ini membuat bentuk pada posisi mouse, ketika pengguna mengeklik dua kali diagram. Dalam Definisi Bahasa Khusus Domain untuk sampel ini, properti FillColor
dari ExampleShape
telah diekspos.
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();
}
}
}
Jika Anda menyediakan lebih dari satu bentuk, atur posisi relatifnya menggunakan AbsoluteBounds
.
Anda juga dapat mengatur warna dan properti konektor lain yang diekspos menggunakan metode ini.
Penggunaan Transaksi
Bentuk, konektor, dan diagram adalah subjenis ModelElement dan bersifat langsung di Store. Oleh karena itu, Anda harus melakukan perubahan hanya di dalam transaksi. Untuk mendapatkan informasi selengkapnya, lihat Cara: Menggunakan Transaksi untuk Memperbarui Model.
Tampilan Dokumen dan Data Dokumen
Partisi Store
Ketika model dimuat, diagram yang menyertainya dimuat secara bersamaan. Biasanya, model dimuat ke Store.DefaultPartition, dan konten diagram dimuat ke Partisi lain. Biasanya, konten setiap partisi dimuat dan disimpan ke file terpisah.