C# - A fejlesztőeszköz objektumainak elérése

forráskód letöltése
A Visual Studio.NET keretrendszer nemcsak minden elődjét meghaladva teszi lehetővé alkalmazások fejlesztését, de számtalan kényelmi funkcióval is rendelkezik. Egy komplett objektummodell segítségével kapcsolatot is teremthetünk a keretrendszer, és beépülő moduljaink, vagy makróink között. Cikkünkben ezt a lehetőséget járjuk körbe, bemutatva néhány osztályt, és ezek funkcionalitását.
A mellékelt projekt IDEMacro alkönyvtárában található makró-projektet (IDEMacro.vsmacros állomány) töltse be a keretrendszerbe, a Macro Explorer segítségével. Ehhez az ablak gyorsmenüben válassza a Load Macro Project menüpontot.
A Visual Studio.NET keretrendszer rendelkezik egy programozható, projekt-semleges objektum modellel, melynek segítségével hozzáférhetünk az IDE architektúráját képező komponensekhez. Ez a kiterjesztett modell olyan komponensek halmaza, melyek reprezentálják a projekt egységeket, a különböző IDE eszközök ablakait, a kódszerkesztő ablakot, a debugger alprogramot, a kód objektumait, a szerkesztett dokumentumokat, valamint a különböző eseményeket.
Ezeket felhasználva automatizálhatunk bizonyos funkciókat a keretrendszerben, például egy kattintással adhatunk új állományt az adott projekthez, vagy hozhatunk létre tetszőleges projektet.
Mindezekhez egy referenciát kell csupán hozzáadni az adott projekthez a VSLangProj.dll assembly-re. A komponensre a VSLangProj kulcsszóval hivatkozhatunk.
A VSLangProj névtér számtalan osztályt tartalmaz, melyek lehetővé teszik a műveletet a keretrendszer eszközeivel. A névtér fontos osztálya a VSProject, melynek segítségével a keretrendszerbe betöltődő C# és Visual Basic projektekről szerezhetünk információkat. A VSProject objektummal az objektum-modell többi objektumát is könnyedén elérhetjük.
A VSProject osztály rendelkezik egy tagobjektummal – References -, melynek segítségével lekérdezhetők, vagy Remove metódusának segítségével eltávolíthatók az adott projekthez rendelt referenciák (COM, ActiveX hivatkozások). A References tagobjektummal nem férhetünk hozzá a projekt Webes referenciáihoz, erre a ProjectItems property, és az ezen keresztül elérhető objektum alkalmas.
Az objektummodell elemeit demonstrálandó, elkészítettünk egy makró-projektet, melyben három metódust implementáltunk.
A mellékelt makró ProjectInIDE és CSProjectCount metódusai csak abban az esetben használhatóak, illetve mutatnak látható eredményt, ha egy vagy több projekt betöltődött a keretrendszerbe. Ennek érdekében a makró használata előtt töltsük be a mellékelt C# projektet.
A makrót – ahogy a cikk elején jeleztük – be kell tölteni a makró-gyűjteménybe, ahol már található alapértelmezésben előre létrehozott makró. Ezek mellé bekerül a mi makrónk is.

A makró kódját a Visual Studio.NET keretrendszer beépített makró szerkesztőjében nézhetjük meg, melyet a Tools menüből indíthatunk el. A Macros alpontból nyíló menüben válasszuk a Macros IDE pontot, vagy egyszerűen nyomjuk le a CTRL + F11 billentyűkombinációt.
A makró szerkesztőben Visual Basic nyelven hozhatunk létre makrókat. Látható a szerkesztő Project Explorer ablakában, ha megnyitjuk az IDEMacro projektünk References csomópontját, hogy a VSLangProj és az EnvDTE névterekre már alapértelmezésben meg van adva egy-egy referencia. Nincs más teendőnk, mint ezekre a névterekre megadni a kódban a hivatkozásokat.

Imports EnvDTE
Imports VSLangProj
A makró rendelkezik egy Maodule1 modullal, mely a létrehozott függvények kódját tartalmazza. A MakeProject függvény segítségével egy kattintással létrehozhatunk egy tetszőleges nevű Window-os projektet, mely a C# nyelvet használja.
Ha megvizsgáljuk a Visual Studio.NET mappáját, akkor a VC# alkönyvtárban találunk mappákat, melyek .vsz kiterjesztésű állományokat tartalmaznak. Ugyanezeket a mappákat és állományokat megtaláljuk a VS.NET VB7 és VC7 mappájában is. Ezek az állományok – template – tulajdonképpen minták, melyek alapján az IDE egy adott projekttípus kiválasztásakor létrehozza a kívánt állományokat.
A VC# mappában a CSharpProjects alkönyvtárban vizsgáljuk meg a CSharpEXE.vsz állományt. Az állomány kevés sort tartalmaz, tulajdonképpen csak konfigurációs beállításokat a projekt típusára vonatkozóan. Többek közt látható, hogy a projekt gerincállományának kiterjesztése .csproj.
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine
Param="WIZARD_NAME = CSharpEXEWiz"
Param="WIZARD_UI = FALSE"
Param="PROJECT_TYPE = CSPROJ"
A makrónk MakeProject metódusában ezt az állományt használjuk fel ahhoz, hogy egy adott néven létrehozzunk egy Windows-os alkalmazás projektet. Lássuk, hogyan is történik a művelet.
Sub MakeProject()
A template nevű karakterláncban eltároljuk a fent említett állomány teljes elérési útvonalát. Ennek érdekében az EnvDTE névtér DTE osztályát hívjuk segítségül, melynek a Solution tagobjektuma és annak TemplatePath metódusa lesz a kulcs a várt karakterlánc lekérdezésben.
  Dim template As String
  template = DTE.Solution.TemplatePath(VSLangProj.PrjKind.prjKindCSharpProject) & "CSharpEXE.vsz"
A metódus paraméterként a PrjKind felsorolt típus egyik elemét tartalmazza, mely utal arra, hogy C#-os projektet kell létrehozni, és az ehhez tartozó template útvonalára van szükségünk. Az így adódott karakterlánchoz hozzácsapjuk a választott konkrét állomány nevét.
A következő lépés, hogy egy panelen bekérjük a létrehozandó projekt nevét, mely egyben a mappa neve is lesz.
  Dim newProject As Project
  Dim name As String = InputBox("Adja meg a létrehozandó projekt nevét: ")
A mappa a rendszermeghajtó Program Files mappájában jön létre. Ezt az Environment osztály SpecialFolder felsorolt típusának segítségével adjuk meg.
  Dim folder As String
  folder = System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
A projekt létrehozását pedig a Solution tagobjektum AddFromTemplate metódusával végezzük, ahol az első paraméter tartalmazza a .vsz állomány teljes elérési útvonalát, a második a mappa nevét, harmadik pedig a projekt nevét. Amennyiben a negyedik paraméterben TRUE értéket adunk meg, a projekt nem a jelenleg betöltött solution-höz kapcsolódik, hanem annak helyére töltődik be.
  newProject = DTE.Solution.AddFromTemplate(template, folder & "\" & name, name, True)
End Sub
A metódus visszatérési értéke egy Project típusú objektum, melyet később felhasználhatunk.
A makró ProjectInIDE metódusában az aktuálisan betöltött projektek .csproj állományainak teljes elérési útvonalát jeleníthetjük meg egy üzenet panelen.
Sub ProjectInIDE()
  Dim aProject As Project
  For Each aProject In DTE.CSharpProjects
    MsgBox(aProject.FullName)
  Next
End Sub
Ekkor a DTE osztály CSharpProjects kollekciójának elemeit lapozhatjuk végig egy ciklussal, majd a kollekció elemeinek – melyek Project típusú objektumok – kérdezhetjük le a FullName property-jét.
A CSProjectCount metódussal meg is számlálhatjuk a betöltött projecteket, melyek C# nyelven íródnak.
Sub CSProjectCount()
  Dim projectsCount As Integer = 0
  Dim aProject As Project
  For Each aProject In DTE.Solution.Projects
    If (aProject.Kind = PrjKind.prjKindCSharpProject) Then
      projectsCount += 1
    End If
  Next
  MsgBox("CSharp projektek darabszáma: " & projectsCount & " darab")
End Sub
Ekkor úgy járunk el, hogy a Project objektum Kind property-jét kérdezzük le, mely tartalmazza a projekt típusát. Ha ennek értéke PrjKind felsorolt típus prjKindCSharpProject elemével egyezik meg, akkor a változó értékét növeljük.