Aracılığıyla paylaş


Program Kodunda Modele Gitme ve Modeli Güncelleştirme

Model öğelerini oluşturmak ve silmek, özelliklerini ayarlamak ve öğeler arasında bağlantılar oluşturup silmek için kod yazabilirsiniz. Tüm değişiklikler bir işlem içinde yapılmalıdır. Öğeler diyagramda görüntüleniyorsa, diyagram işlemin sonunda otomatik olarak "düzeltilir".

Örnek DSL Tanımı

Bu konu başlığı altındaki örnekler için DslDefinition.dsl dosyasının ana bölümü budur:

DSL Tanımı diyagramı - aile ağacı modeli

Bu model, bu DSL'nin bir örneğidir:

Tudor Aile Ağacı Modeli

Referanslar ve Ad Alanları

Bu konudaki kodu çalıştırmak için aşağıdakilere başvurmanız gerekir:

Microsoft.VisualStudio.Modeling.Sdk.11.0.dll

Kodunuz şu ad alanını kullanır:

using Microsoft.VisualStudio.Modeling;

Ayrıca, kodu DSL'nizin tanımlandığı projeden farklı bir projede yazıyorsanız, DSL projesi tarafından oluşturulan derlemeyi içeri aktarmanız gerekir.

Özellikler

DSL tanımında tanımladığınız etki alanı özellikleri, program kodunda erişebileceğiniz özelliklere dönüşür:

Person henry = ...;

if (henry.BirthDate < 1500) ...

if (henry.Name.EndsWith("VIII")) ...

Bir özellik ayarlamak istiyorsanız, bunu bir işlem içinde yapmanız gerekir:

henry.Name = "Henry VIII";

DSL tanımında bir özelliğin Kind'iHesaplanmış ise, bunu ayarlayamazsınız. Daha fazla bilgi için bkz. Hesaplanan ve Özel Depolama Özellikleri.

Ilişki

DSL tanımında etki alanı ilişkileri tanımladığınızda, bunlar ilişkinin her iki ucundaki sınıflarda birer özellik çifti oluşturur. Özelliklerin adları DslDefinition diyagramında ilişkinin her tarafındaki rollerde etiketler olarak görünür. Rolün çokluğuna bağlı olarak, özelliğin türü ilişkinin diğer ucundaki sınıf veya bu sınıfın koleksiyonudur.

foreach (Person child in henry.Children) { ... }

FamilyTreeModel ftree = henry.FamilyTreeModel;

İlişkinin karşı uçlarında yer alan özellikler her zaman karşılıklıdır. Bir bağlantı oluşturulduğunda veya silindiğinde, her iki öğedeki rol özellikleri de güncelleştirilir. Aşağıdaki ifade (hangi System.Linq uzantılarını kullanırsa kullansın), örnekteki ParentsHaveChildren ilişkisi için her zaman doğrudur.

(Person p) => p.Children.All(child => child.Parents.Contains(p))

&& p.Parents.All(parent => parent.Children.Contains(p));

ElementLinks. İlişki, etki alanı ilişki türünün bir örneği olan bağlantı adlı model öğesiyle de temsil edilir. Bağlantının her zaman bir kaynak öğesi ve bir hedef öğesi vardır. Kaynak öğe ve hedef öğe aynı olabilir.

Bağlantıya ve özelliklerine erişebilirsiniz:

ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);

// This is now true:

link == null || link.Parent == henry && link.Child == edward

Varsayılan olarak, bir ilişkinin birden fazla örneğinin herhangi bir model öğesi çiftini bağlamasına izin verilmez. Ancak DSL tanımında, ilişki için Allow Duplicates bayrağı doğruysa, birden fazla bağlantı olabilir ve GetLinks kullanmanız gerekebilir.

foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }

Bağlantılara erişmek için başka yöntemler de vardır. Örneğin:

foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }

Gizli roller. DSL tanımında, Belirli bir rol için Oluşturulan ÖzellikYanlış ise, o role karşılık gelen hiçbir özellik oluşturulmaz. Ancak, yine de bağlantılara erişebilir ve ilişkinin yöntemlerini kullanarak bağlantılarda geçiş yapabilirsiniz:

foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }

En sık kullanılan örnek, bir model öğesini diyagramda görüntüleyen şekle bağlayan ilişkidir PresentationViewsSubject :

PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape

Öğe Dizini

öğe dizinini kullanarak depodaki tüm öğelere erişebilirsiniz:

store.ElementDirectory.AllElements

Öğeleri bulmak için aşağıdakiler gibi yöntemler de vardır:

store.ElementDirectory.FindElements(Person.DomainClassId);

store.ElementDirectory.GetElement(elementId);

Sınıf Bilgilerine Erişme

DSL tanımının sınıfları, ilişkileri ve diğer yönleri hakkında bilgi alabilirsiniz. Örneğin:

DomainClassInfo personClass = henry.GetDomainClass();

DomainPropertyInfo birthProperty =

personClass.FindDomainProperty("BirthDate")

DomainRelationshipInfo relationship =

link.GetDomainRelationship();

DomainRoleInfo sourceRole = relationship.DomainRole[0];

Model öğelerinin üst sınıfları aşağıdaki gibidir:

  • ModelElement - tüm öğeler ve ilişkiler ModelElement'lerdir

  • ElementLink - tüm ilişkiler ElementLink'lerdir

İşlem İçinde Değişiklik Yapma

Program kodunuz Mağaza'daki herhangi bir şeyi değiştirdiğinden, bunu bir işlem içinde yapması gerekir. Bu, tüm model öğeleri, ilişkiler, şekiller, diyagramlar ve bunların özellikleri için geçerlidir. Daha fazla bilgi için bkz. Transaction.

Bir işlemi yönetmenin en uygun yolu, bir try...catch deyimi içine alınmış using deyimidir.

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

Bir işlem içinde istediğiniz sayıda değişiklik yapabilirsiniz. Etkin bir işlem içinde yeni işlemler açabilirsiniz.

Değişikliklerinizi kalıcı hale getirmek için, atılmadan önce işlemi onaylamanız gerekir Commit. İşlem içinde yakalanmayan bir istisna oluşursa, Depo değişikliklerden önceki durumuna sıfırlanır.

Model Öğeleri Oluşturma

Bu örnek, mevcut modele bir öğe ekler:

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

Bu örnekte, öğe oluşturmayla ilgili şu temel noktalar gösterilmektedir:

  • Yeni öğeyi Mağaza'nın belirli bir bölümünde oluşturun. Model öğeleri ve ilişkiler için, ancak şekiller için değil, bu genellikle varsayılan bölümdür.

  • Ekleme ilişkisinin hedefi haline getirin. Bu örneğin DslDefinition bölümünde her Kişi FamilyTreeHasPeople ilişkisini eklemenin hedefi olmalıdır. Bunu başarmak için, Person nesnesinin FamilyTreeModel rol özelliğini ayarlayabilir veya Kişi'yi FamilyTreeModel nesnesinin Kişiler rol özelliğine ekleyebiliriz.

  • Yeni bir öğenin özelliklerini ayarlayın, özellikle DslDefinition'da true olan özelliği IsName olacak şekilde dikkatlice yapılandırın. Bu bayrak, bir ögenin kendi sahibinin içinde benzersiz olarak tanımlanmasını sağlayan özelliği belirtir. Bu durumda Name özelliğinde bu bayrak bulunur.

  • Bu DSL'nin DSL tanımı Mağaza'ya yüklenmiş olmalıdır. Menü komutu gibi bir uzantı yazıyorsanız, bu genellikle zaten doğru olacaktır. Diğer durumlarda, modeli mağazaya açıkça yükleyebilir veya model yüklemek için ModelBus kullanabilirsiniz. Daha fazla bilgi için bkz . Nasıl yapılır: Program Kodunda Dosyadan Model Açma.

    Bu şekilde bir öğe oluşturduğunuzda, otomatik olarak bir şekil oluşturulur (DSL'nin diyagramı varsa). Varsayılan şekil, renk ve diğer özelliklerle otomatik olarak atanan bir konumda görünür. İlişkili şeklin nerede ve nasıl görüneceğini denetlemek istiyorsanız bkz. Öğe oluşturma ve şekli.

Örnek DSL tanımında tanımlanan iki ilişki vardır. Her ilişki, ilişkinin her sonundaki sınıfta bir rol özelliği tanımlar.

bir ilişkinin örneğini oluşturmanın üç yolu vardır. Bu üç yöntemin her biri aynı etkiye sahiptir:

  • Kaynak rol oynatıcının özelliğini ayarlayın. Örneğin:

    • familyTree.People.Add(edward);

    • edward.Parents.Add(henry);

  • Hedef rol oynatıcının özelliğini ayarlayın. Örneğin:

    • edward.familyTreeModel = familyTree;

      Bu rolün çokluğudur 1..1, bu nedenle değeri atarız.

    • henry.Children.Add(edward);

      Bu rolün çokluk değeri 0..* olduğundan, koleksiyona ekliyoruz.

  • İlişkinin bir örneğini açıkça oluşturun. Örneğin:

    • FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);

    • ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);

    Son yöntem, ilişkinin kendisinde özellikleri ayarlamak istiyorsanız kullanışlıdır.

    Bu şekilde bir öğe oluşturduğunuzda, diyagramdaki bir bağlayıcı otomatik olarak oluşturulur, ancak varsayılan bir şekil, renk ve diğer özelliklere sahiptir. İlişkili bağlayıcının nasıl oluşturulduğunu denetlemek için bkz. Öğe ve Şekil Oluşturma.

Öğeleri Silme

Öğeyi silmek için Delete() çağırarak bir öğeyi silin.

henry.Delete();

Bu işlem şunları da siler:

  • Öğeye ve öğeden ilişki bağlantıları. Örneğin, edward.Parents artık içermeyecektir henry.

  • PropagatesDelete bayrağının true olduğu rollerdeki öğeler. Örneğin, öğesini görüntüleyen şekil silinir.

Varsayılan olarak, her ekleme ilişkisinin hedef rolünde PropagatesDelete true değeri vardır. henry öğesini silmek, familyTree öğesini silmez. Ancak, familyTree.Delete() tüm Persons öğesini siler.

Varsayılan olarak, PropagatesDelete başvuru ilişkilerinin rolleri için doğru değildir.

Bir nesneyi sildiğinizde, silme kurallarının belirli bulaşmaları göz ardı etmesine neden olabilirsiniz. Bu, bir öğeyi başka bir öğe için değiştiriyorsanız kullanışlıdır. Silme işleminin yayılmaması gereken bir veya daha fazla rolün GUID'sini sağlarsınız. GUID, ilişki sınıfından alınabilir:

henry.Delete(ParentsHaveChildren.SourceDomainRoleId);

(Çünkü PropagatesDelete ilişkisi, ParentsHaveChildren ilişkisindeki roller için false olduğundan, bu özel örneğin hiçbir etkisi olmaz.)

Bazı durumlarda silme işlemi, öğede veya yayma tarafından silinecek bir öğede bir kilidin bulunmasıyla engellenir. öğesinin silinip silinemeyeceğini denetlemek için kullanabilirsiniz element.CanDelete() .

Bir öğeyi rol özelliğinden kaldırarak ilişki bağlantısını silebilirsiniz:

henry.Children.Remove(edward); // or:

edward.Parents.Remove(henry); // or:

Ayrıca bağlantıyı açıkça silebilirsiniz:

edwardHenryLink.Delete();

Bu üç yöntemin tümü aynı etkiye sahiptir. Bunlardan yalnızca birini kullanmanız gerekir.

Rolün 0..1 veya 1..1 çokluğu varsa, bunu nullolarak veya başka bir değere ayarlayabilirsiniz:

edward.FamilyTreeModel = null; veya:

edward.FamilyTreeModel = anotherFamilyTree;

bir İlişkinin Bağlantılarını Yeniden Sıralama

Belirli bir model öğesinde kaynaklanan veya hedeflenen belirli bir ilişkinin bağlantıları belirli bir diziye sahiptir. Eklendikleri sırada görünürler. Örneğin, bu ifade her zaman alt ögeleri aynı sırada verir:

foreach (Person child in henry.Children) ...

Bağlantıların sırasını değiştirebilirsiniz:

ParentsHaveChildren link = GetLink(henry,edward);

ParentsHaveChildren nextLink = GetLink(henry, elizabeth);

DomainRoleInfo role =

link.GetDomainRelationship().DomainRoles[0];

link.MoveBefore(role, nextLink);

Locks

Değişiklikleriniz bir kilit tarafından engellenebilir. Kilitler tek tek öğelerde, bölümlerde ve depolama alanında ayarlanabilir. Yapmak istediğiniz değişiklik türünü engelleyen bir kilit bu düzeylerden herhangi birinde varsa, bunu denediğinizde bir istisna fırlatılabilir. Kilitlerin ayarlanıp ayarlanmadığını anlamak için, ad alanı Microsoft.VisualStudio.Modeling.Immutability içinde tanımlanan bir uzantı yöntemi olan element.GetLocks() kullanılabilir.

Daha fazla bilgi için bkz. Read-Only Segmentleri Oluşturmak için Kilitleme İlkesi Tanımlama.

Kopyala ve Yapıştır

Öğeleri veya öğe gruplarını IDataObject'a kopyalayabilirsiniz:

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

Öğeler serileştirilmiş Öğe Grubu olarak depolanır.

Bir IDataObject öğesindeki öğeleri bir modelle birleştirebilirsiniz:

using (Transaction t = targetDiagram.Store.
        TransactionManager.BeginTransaction("paste"))
{
  adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}

Merge () ya bir PresentationElement ya da bir ModelElement kabul edebilir. Bir verirseniz PresentationElement, hedef diyagramda üçüncü parametre olarak bir konum da belirtebilirsiniz.

Diyagramlarda gezinme ve diyagramları güncelleştirme

DSL'de, Person veya Song gibi bir kavramı temsil eden etki alanı modeli öğesi, diyagramda gördüklerinizi temsil eden şekil öğesinden ayrıdır. Etki alanı modeli öğesi, kavramların önemli özelliklerini ve ilişkilerini depolar. Şekil öğesi diyagramda nesne görünümünün boyutunu, konumunu ve rengini ve bileşen parçalarının düzenini depolar.

Sunu Öğeleri

Temel şekil ve öğe türlerinin sınıf diyagramı

DSL Tanımınızda, belirttiğiniz her öğe aşağıdaki standart sınıflardan birinden türetilen bir sınıf oluşturur.

Öğe türü Temel sınıf
Etki alanı sınıfı ModelElement
Etki alanı ilişkisi ElementLink
Shape NodeShape
Connector BinaryLinkShape
Diagram Diagram

Diyagramdaki bir öğe genellikle bir model öğesini temsil eder. Genellikle (ancak her zaman değil), bir NodeShape etki alanı sınıfı örneğini ve bir BinaryLinkShape etki alanı ilişki örneğini temsil eder. İlişki, PresentationViewsSubject bir düğüm veya bağlantı şeklini temsil ettiği model öğesine bağlar.

Her düğüm veya bağlantı şekli bir diyagrama aittir. İkili bağlantı şekli iki düğüm şeklini bağlar.

Şekiller, iki kümede alt şekiller barındırabilir. Kümedeki NestedChildShapes bir şekil, üst öğesinin sınırlayıcı kutusuyla sınırlandırılır. Listedeki RelativeChildShapes şekil, ana öğe sınırlarının tamamen ya da kısmen dışında, örneğin bir etiket veya bağlantı noktası olarak, görünebilir. Diyagramda RelativeChildShapes ve Parent yoktur.

Şekiller ve öğeler arasında gezinme

Alan modeli öğeleri ve şekil öğeleri PresentationViewsSubject ile ilişkilidir.

// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape =
  PresentationViewsSubject.GetPresentation(henry)
    .FirstOrDefault() as PersonShape;

Aynı ilişki, ilişkileri diyagramdaki bağlayıcılara bağlar:

Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
   PresentationViewsSubject.GetPresentation(link)
     .FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape

Bu ilişki ayrıca modelin kökünü diyagrama bağlar:

FamilyTreeDiagram diagram =
   PresentationViewsSubject.GetPresentation(familyTree)
      .FirstOrDefault() as FamilyTreeDiagram;

Bir şekille temsil edilen model öğesini almak için şunu kullanın:

henryShape.ModelElement as Person

diagram.ModelElement as FamilyTreeModel

Genel olarak diyagramdaki şekiller ve bağlayıcılar arasında gezinmek önerilmez. Modeldeki ilişkilerde gezinmek, şekiller ve bağlayıcılar arasında yalnızca diyagramın görünümü üzerinde çalışmak gerektiğinde gezinmek daha iyidir. Bu yöntemler bağlayıcıları her uçta şekillere bağlar:

personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes

connector.FromShape, connector.ToShape

Birçok şekil bileşiktir; bir ana şekil ve bir veya daha fazla alt katmandan oluşur. Başka bir şekle göre konumlandırılan şekillerin alt öğeleri olduğu söylenir. Üst şekil hareket ettiğinde, alt öğeler de onunla birlikte hareket eder.

Göreli alt öğeler ebeveyn şeklin sınırlayıcı kutusunun dışında görünebilir. İç içe geçmiş alt öğeler, kesinlikle üst öğe sınırlarının içinde görünür.

Diyagramdaki en üst şekil kümesini elde etmek için şunu kullanın:

Diagram.NestedChildShapes

Şekillerin ve bağlayıcıların ata sınıfları şunlardır:

ModelElement

-- PresentationElement

-- ShapeElement

----- NodeShape

------- Diagram

------- Şekliniz

----- LinkShape

------- BinaryLinkShape

--------- YourConnector

Şekillerin ve Bağlayıcıların Özellikleri

Çoğu durumda, şekillerde açık değişiklikler yapmak gerekli değildir. Model öğelerini değiştirdiğinizde, "düzeltme" kuralları şekilleri ve bağlayıcıları güncelleştirir. Daha fazla bilgi için bkz. Değişiklikleri Yanıtlama ve Yayma.

Ancak, model öğelerinden bağımsız özelliklerdeki şekillerde bazı açık değişiklikler yapmak yararlıdır. Örneğin, şu özellikleri değiştirebilirsiniz:

  • Size - şeklin yüksekliğini ve genişliğini belirler.

  • Location - ebeveyn şekle veya diyagrama göre konum

  • StyleSet - şekli veya bağlayıcıyı çizmek için kullanılan kalem ve fırça kümesi

  • Hide - şekli görünmez yapar

  • Show - bir Hide() sonra şekli görünür hale getirir.

Öğe ve Şekli Oluşturma

Bir öğe oluşturduğunuzda ve bu öğeyi ilişkileri ekleme ağacına bağladığınızda, şekil otomatik olarak oluşturulur ve onunla ilişkilendirilir. Bu işlem, işlemin tamamlanmasının ardından yürütülen "düzeltme" kuralları tarafından gerçekleştirilir. Ancak, şekil otomatik olarak atanan bir konumda görünür ve şekli, rengi ve diğer özellikleri varsayılan değerlere sahip olur. Şeklin nasıl oluşturulduğunu denetlemek için birleştirme işlevini kullanabilirsiniz. Önce bir ElementGroup'a eklemek istediğiniz öğeleri eklemeniz ve ardından grubu diyagramda birleştirmeniz gerekir.

Bu yöntem:

  • Öğe adı olarak bir özellik atadıysanız adı ayarlar.

  • DSL Tanımında belirttiğiniz tüm Öğe Birleştirme Yönergelerini gözlemler.

Bu örnek, kullanıcı diyagrama çift tıkladığında fare konumunda bir şekil oluşturur. Bu örnek için DSL Tanımında FillColor özelliği ExampleShape görünür hale getirildi.

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

Birden fazla şekil sağlarsanız, AbsoluteBounds kullanarak onların göreli konumlarını ayarlayın.

Bu yöntemi kullanarak bağlayıcıların rengini ve diğer kullanıma sunulan özelliklerini de ayarlayabilirsiniz.

İşlem Kullanımı

Şekiller, bağlayıcılar ve diyagramlar, ModelElement'ın alt türleridir ve Mağaza'da bulunur. Bu nedenle, bu işlemlerde yalnızca bir işlem içinde değişiklik yapmanız gerekir. Daha fazla bilgi için bkz . Nasıl yapılır: Modeli Güncelleştirmek için İşlemleri Kullanma.

Belge Görünümü ve Belge Verileri

Standart diyagram türlerinin sınıf diyagramı

Bölümleri Depola

Bir model yüklendiğinde, eşlik eden diyagram aynı anda yüklenir. Genellikle model Store.DefaultPartition'a yüklenir ve diyagram içeriği başka bir Bölüme yüklenir. Genellikle her bölümün içeriği yüklenir ve ayrı bir dosyaya kaydedilir.