Sunteți pe pagina 1din 7

Modalitati de accesare si modificare a elementelor

modelelor in codul de program (C#).


Navigarea modelului
Oricarui element din metamodel (DslDefinition.dsl) de fapt corespunde o clasa cu
proprietati, care corespund proprietatilor si relatiilor definite in metamodel.
Aceasta clasa este derivata dintr-o anumita clasa (in dependenta de tipul
elementului) predefinita si mosteneste un set de metode, care permit accesarea,
modificarea elementelor si proprietatilor lor, si navigarea in model.
Fiecare element din metamodel este legat cu notatia lui. Acestei notatiei tot
corespunde o clasa derivata dintr-o anumita clasa de prezentare (vezi fig.1 . roz
elemente model, albastru - reprezentari)

Fig.1 Clase de baza pentru elementele metamodelului


Modelul particular creat in baza metamodelului reprezinta de fapt Instantele
(obiectele) claselor definite in metamodel :
PageElement aPage = ... ;// clasa derivata din clasa ModelElement

Instantele claselor definite in DslDefinition.dsl sunt pastrate intr-o structura de


date speciala numita In-Memory Store (IMS) sau Store. Orice clasa definita in DSL
preia Store ca argument al constructorului. De exemplu:

PageElement page = new PageElement (theStore);

Proprietati
Proprietatile claselor definite in metamodelul DSL, devin proprietatile claselor in
codul de program corespunzator:
PageElement aPage = ... ;
if (aPage.isRoot == True) ... ;
if (aPage.Address.EndsWith(".html")) ... ;

Daca intre doua clase este definite o relatie, atunci instantele ambelor clase au
proprietati, care permit navigarea catre capatul opus al legaturii. Denumirile
proprietatilor apar in metamodel ca etichetele rolurilor asupra ambelor capetelor
relatiei. In dependenta de multiplicitatea rolului, tipul proprietatii
corespunzatoare va fi o clasa sau o colectie de clase. De exemplu, daca avem o
relatie numita ParintiAuCopii intre doua Persoane, capetele relatiei avand roluri
multiple Parinti si, respectiv, Copii, atunci poate fi scris codul urmator:
Ion.Copii.Add(Maria);
// adaugarea relatiei intre obiect Ion si Maria, unde Maria este copil

Acum ambele expresii sunt adevarate:


Ion.Copii.Contains(Maria);
Maria.Parinti.Contains(Ion);

Acelasi effect ar putea fi atins prin scrierea:


Maria.Parinti.Add(Ion);

Accesarea fiecarului element din colectie:


foreach (Persoana copil in Ion.Copii) { ... }

Relatii
O relatie din metamodelul DSL poate avea instante intr-un model particular.
Instantele relatiei se numesc legaturi. O legatura intotdeauna are un elementsursa si un element-destinatie. Tipul lor poate fi acelasi. Obiectul legaturii si
proprietatile lui (sursa si destinatie) pot fi accesate in felul urmator:

ParintiAuCopii legatura = ParintiAuCopii.GetLink(Ion, Maria);


if (legatura.Parent == Ion) {...}
if (legatura.Child == Maria) {...}

Daca in metamodel se permit legaturi multiple intre elemente, atunci aceste


legaturi sun accesate cu ajutorul GetLinks:
foreach (ParintiAuCopii legatura in ParintiAuCopii.GetLinks(Ion, Maria)) {...}

sau
foreach (ParintiAuCopii legatura in ParintiAuCopii.GetLinksToChildren(Ion)) {...}

In metamodelul (definitia DSL) la unele roluri particulare proprietatea Is


Property Generated pot avea valoarea false. Atunci pentru acest rol nu este
generata proprietatea. Totusi si in acest caz legaturile pot fi accesate si
traversate, utilizand metodele clasei-relatie:
foreach (Persoana p in ParintiAuCopii.GetChildren(Ion)) { ... }

Un exemplu de relatie cu rolurile ascunse este relatia


PresentationViewsSubject, care leaga elementul modelului cu figura, care il
reprezinta pe diagram
PresentationViewsSubject.GetPresentation(aPage)[0] as PageShape

Directoriu de elemente
Toate elementele din deposit Store pot fi accesate utilizand directoriu de
elemente:
store.ElementDirectory.AllElements

Metode pentru gasirea elementelor:


store.ElementDirectory.FindElements(Persoana.DomainClassId);
store.ElementDirectory.GetElement(elementId);

Accesarea Informatiilor despre clase, relatii si alte aspecte ale


metamodelului
Exemple:
DomainClassInfo pageClass = aPage.GetDomainClass();
DomainPropertyInfo addressProperty =
pageClass.FindDomainProperty("Address")

DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];

Modificarea modelului
Oriche schimbare in model (in elemente, relatii, figuri, diagrame etc. ) trebuie
facuta in asa numita tranzactie. De exemplu:
using (Transaction t = store.TransactionManager.BeginTransaction("updates"))
{
// schimbari in depozit
t.Commit();
}

Daca o exceptie are loc in timpul schimbarilor, astfel incat metoda Commit() nu
este indeplinita, atunci depozitul Store va fi resetat in starea sa initiala. Astfel
modelul niciodata nu va fi inconsistent.
Cea mai buna metoda este utilizarea instructiunii try catch:

Store store; ...


SiteModel site = ...// element-radacina a modelului
try
{
using (Transaction transaction =
store.TransactionManager.BeginTransaction("update model"))
// tranzactia trebuie sa aiba denumirea.
{

// Schimbari in depozitul Store:


Page p = new Page(store);
p.SiteModel = site; //
p.Name = "About";
p.Address = "about.html";
// sfarsitul schimbarilor

transaction.Commit(); // Important!

} // tranzactia s-a incheiat


}
catch (Exception ex)
{
// Daca apare o exceptie, depozitul va fi restabilit
// in starea precedenta.
}

In cadrul tranzactiei poate fi facut orice numar de schimbari. Tranzactii noi pot fi
deschise in cadrul unei tranzactiei active. Apelul la metoda Commit la incheierea
tranzactiei face toate schimbarile permanente. In cazul unei exceptiei depozitul
restabileste starea precedenta.

Accesarea modelelor din sabloane T4


Notiuni de baza despre sabloane
Utilizand sabloane T4 poate fi generat orice fisier text (rapoarte, codul sursa,
fisiere de configurare, XML, HTML, etc).
Sabloane textuale sunt prelucrare in regimul experimental, cand depanati DSL,
sau acolo unde veti amplasa limbajul.

Sabloanele se pastreaza in fisiere textuale cu extensia .tt si contin urmatoarele


tipuri de constructii :

Directivele elemente care controleaza modul de procesare a sablonului.


Blocuri text - continut copiat direct, fara schimbari in fisierul rezultant.
Blocuri de control cod de program care insereaza valorile variabilelor
in text, si controleaza generarea conditionata sau repetata a textului.

Directivele sunt instructii generatorului despre cum, in baza carui model si unde
va fi generat codul. Exemplu de directiva (observati formatarea/marcajul) :
<#@ output extension=".txt" #>

Textul nu are nici o formatare speciala si se copie fara nici o schimbare, pastrand
pozitia initiala. In exemplu urmator va fi generat fisier txt care contine cuvantul
Hello :
<#@ output extension=".txt" #>
Hello

Blocuri de control contin instructiunile utilizate pentru generarea. Implicit


limbajul instructiunilor este C#, dar poate fi utilizat si limbajul Visual Basic (VB).
Orice bloc de contrul este delimitat de simbolurile <# ... #>
In exemplu urmator in fisierul rezultant va fi scris cuvantul Hello :
<# Write(Hello) #>

In sabloane t4 blocuri de control nu pot contine alte blocuri de control, dar pot fi
mixate cu blocuri de text :
<#
for(int i = 0; i < 4; i++)
{
#>
Hello!
<#
}
#>

Exista o variatie a blocurilor de control, utilizata pentru calcularea expresiilor si


inserarea valorii in text. Blocuri de control de tip expresie se delimiteaza prin
simbolurile <#= ... #>
Exemplu:
<#@ output extension=".txt" #>
<#
for(int i = 0; i < 4; i++)
{
#>

This is hello number <#= i+1 #>: Hello!


<#
}
#>

Accesarea modelului din sablon


Pentru a accesa modelul dintr-un sablon trebuie:
De adaugat in directiva template proprietatea
inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTr
ansformation" pentru a avea acces la depozitul modelului Store
De specificat procesorul de directive, care va permite accesarea tuturor claselor,
relatiilor etc din model si va incarca modelul din fisierul specificat
Exemplu:
<#@ template
inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransfor
mation" #>
<#@ output extension=".txt" #>
<#@ MyLanguage processor="MyLanguageDirectiveProcessor"
requires="fileName='Sample.myDsl1'" #>

Sablonul acum permite urmatoarele:

Utilizarea claselor domeniului, proprietatilor, relatiilor definite in


metamodel.
Modelul necesar se incarca utilizand proprietatea requires.
Obiectul this are o proprietate, care contine elemental-radacina al
modelului. Incepand de la acest obiect puteti naviga orice alt element al
modelului. Numele proprietatii coincide cu denumirea clasei-radacina. De
exemplu: this.SiteModel.

Un sablon poate accesa mai multe modele:


<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor"
requires="fileName='Library.xyz'" provides="ExampleModel=LibraryModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor"
requires="fileName='School.xyz'" provides="ExampleModel=SchoolModel" #>

S-ar putea să vă placă și