{"id":55000188,"date":"2019-08-01T00:00:00","date_gmt":"2020-03-27T19:38:51","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=188"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Klassen_Methoden_und_Co_per_Code_generieren","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Klassen_Methoden_und_Co_per_Code_generieren\/","title":{"rendered":"Klassen, Methoden und Co. per Code generieren"},"content":{"rendered":"<p><b>Im Beitrag &#8220;Visual Studio mit LINQPad: Project und ProjectItems&#8221; haben wir uns angesehen, wie Sie per Code auf Project-, Solution- und ProjectItem-Elemente zugreifen. Nun wollen wir uns den Umgang mit den ProjectItem-Objekten ansehen und herausfinden, wie wir beispielsweise den enthaltenen Code manipulieren k&ouml;nnen und Klassen, Prozeduren und Variablen anzulegen. Dazu ben&ouml;tigen wir einen Verweis auf das FileCodeModel-Objekt des jeweiligen ProjectItem-Elements. Wie wir das holen und was wir damit anstellen k&ouml;nnen, zeigt der vorliegende Artikel.<\/b><\/p>\n<p>Nachdem wir im oben genannten Artikel gelernt haben, wie wir die Elemente eines Projekts referenzieren, durchlaufen und erstellen, wollen wir uns nun um den Inhalt der Elemente selbst k&uuml;mmern, genau genommen um die Elemente, die Code enthalten. F&uuml;r diese Zwecke gibt es das <b>FileCodeModel<\/b>, dass wir &uuml;ber die gleichnamige Eigenschaft eines jeden <b>Project-Item<\/b>-Elements referenzieren k&ouml;nnen. Die folgende Funktion soll uns das <b>FileCodeModel<\/b>-Element der Klasse liefern, dessen Namen wir mit dem Parameter <b>strItem <\/b>&uuml;bergeben. Die Funktion holt mit der im Artikel <b>Visual Studio mit LINQPad: Project und ProjectItems <\/b>vorgestellten Funktion <b>GetDTE <\/b>einen Verweis auf das <b>DTE<\/b>-Objekt zur Programmierung von Visual Studio und mit der Funktion <b>GetCurrentOrNewProject <\/b>aus dem gleichen Artikel einen Verweis auf das aktuell in Visual Studio ge&ouml;ffnete Projekt. Ist aktuell kein Projekt ge&ouml;ffnet, wird ein neues Projekt erstellt. Danach ermitteln wir &uuml;ber die <b>ProjectItems<\/b>-Auflistung des Projekts das <b>ProjectItem<\/b>-Objekt mit dem Namen aus dem Parameter <b>strItem<\/b>. Schlie&szlig;lich ermitteln wir mit der Eigenschaft <b>FileCodeModel <\/b>einen Verweis auf das gew&uuml;nschte <b>FileCodeModel<\/b>-Objekt, das wir mit der <b>Return<\/b>-Anweisung an die aufrufende Methode zur&uuml;ckgeben:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetFileCodeModel(strItem<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>EnvDTE80.FileCodeModel2\r\n     <span style=\"color:blue;\">Dim <\/span>objDTE<span style=\"color:blue;\"> As <\/span>EnvDTE80.DTE2\r\n     <span style=\"color:blue;\">Dim <\/span>objProject<span style=\"color:blue;\"> As <\/span>EnvDTE.Project\r\n     <span style=\"color:blue;\">Dim <\/span>objProjectItem<span style=\"color:blue;\"> As <\/span>EnvDTE.ProjectItem\r\n     <span style=\"color:blue;\">Dim <\/span>objFileCodeModel<span style=\"color:blue;\"> As <\/span>EnvDTE80.FileCodeModel2\r\n     <span style=\"color:blue;\">If <\/span>GetDTE(objDTE) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>GetCurrentOrNewProject(objProject) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             objProjectItem = objProject.ProjectItems.Item(strItem)\r\n             <span style=\"color:blue;\">Debug.Print<\/span>(objProjectItem.Name)\r\n             objFileCodeModel = Trycast(objProjectItem.FileCodeModel, EnvDTE80.FileCodeModel2)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     Return objFileCodeModel\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Der Aufruf k&ouml;nnte dann etwa wie folgt aussehen, wobei wir die zu verwendende Klasse als Parameter &uuml;bergeben. Danach k&ouml;nnen wir mit dem <b>FileCodeModel <\/b>experimentieren:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objFileCodeModel<span style=\"color:blue;\"> As <\/span>EnvDTE.FileCodeModel\r\nobjFileCodeModel = GetFileCodeModel(\"NeueKlasse.vb\")\r\n<span style=\"color:blue;\">Debug.Print<\/span> (objFileCodeModel.CodeElements.Count)<\/pre>\n<h2>Beispiele zu diesem Artikel<\/h2>\n<p>Die Beispiele finden Sie in der Datei <b>VisualStudioErweitern_Items.linq<\/b>. Sie k&ouml;nnen die einzelnen Prozeduren aufrufen, indem Sie die Aufrufe in der <b>Sub Main<\/b>-Prozedur auskommentieren und <b>Sub Main <\/b>ausf&uuml;hren. Zum Ausprobieren der Prozeduren verwenden Sie das Tool LINQPad, dass Sie unter <b>http:\/\/www.linqpad.net <\/b>herunterladen k&ouml;nnen.<\/p>\n<h2>Eigenschaften und Methoden der FileCodeModel-Klasse<\/h2>\n<p>Die <b>FileCodeModel<\/b>-Klasse hat die folgenden Eigenschaften. Genau genommen schauen wir uns hier nicht die <b>FileCodeModel<\/b>-Klasse an, sondern das <b>FileCodeModel2<\/b>-Interface, das etwas mehr M&ouml;glichkeiten bietet und mit dem Namespace <b>EnvDTE80 <\/b>kommt:<\/p>\n<ul>\n<li><b>CodeElements<\/b>: Auflistung der Code-Elemente. Was genau Code-Elemente sind, schauen wir uns weiter unten an, nachdem wir einige angelegt haben.<\/li>\n<li><b>DTE<\/b>: Verweis auf das &uuml;bergeordnete <b>DTE<\/b>-Objekt.<\/li>\n<li><b>Language<\/b>: Gibt eine GUID aus, welche die verwendete Sprache dieses <b>FileCodeModel<\/b>-Elements repr&auml;sentiert.<\/li>\n<\/ul>\n<pre>         <span style=\"color:blue;\">Debug.Print<\/span> (objFileCodeModel.Language)\r\n           {B5E9BD33-6D3E-4B5D-925E-8A43B79820B4}<\/pre>\n<ul>\n<li><b>Parent<\/b>: Ermittelt das &uuml;bergeordnete Objekt.<\/li>\n<\/ul>\n<p>Dies sind die Methoden der <b>FileCodeModel<\/b>-Klasse:<\/p>\n<ul>\n<li><b>AddAttribute<\/b>: F&uuml;gt ein Attribut wie <b><Assembly: NeuesAttribut(Wert)> <\/b>zu einer Klasse hinzu.<\/li>\n<li><b>AddClass<\/b>: F&uuml;gt eine neue Klasse zum <b>FileCodeModel <\/b>hinzu.<\/li>\n<li><b>AddDelegate<\/b>: F&uuml;gt ein Delegate zum <b>FileCodeModel <\/b>hinzu.<\/li>\n<li><b>AddEnum<\/b>: F&uuml;gt eine Enumeration zum <b>FileCodeModel <\/b>hinzu.<\/li>\n<li><b>AddFunction<\/b>: Hinzuf&uuml;gen von Methoden, Funktionen, Property Get\/Let\/Set-Methoden und so weiter<\/li>\n<li><b>AddImport<\/b>: F&uuml;ge eine <b>Imports<\/b>-Anweisung hinzu.<\/li>\n<li><b>AddInterface<\/b>: Hinzuf&uuml;gen eines Interfaces.<\/li>\n<li><b>AddNamespace<\/b>: F&uuml;gt einen Namespace hinzu.<\/li>\n<li><b>AddStruct<\/b>: F&uuml;gt eine Struktur hinzu.<\/li>\n<li><b>AddVariable<\/b>: F&uuml;gt eine Variable hinzu.<\/li>\n<li><b>CodeElementFromPoint<\/b>:<\/li>\n<li><b>Remove<\/b>:<\/li>\n<\/ul>\n<p>Die meisten der hier genannten <b>Add&#8230;<\/b>-Methoden gibt es auch in der Klasse <b>CodeClass<\/b>. Das hei&szlig;t, Sie erstellen erst ein <b>CodeClass<\/b>-Element, also eine Klasse, referenzieren diese mit einer Objektvariablen wie <b>objClass <\/b>und nutzen dann Methoden wie <b>AddAttribute<\/b>, <b>AddBase<\/b>, <b>AddClass<\/b>, <b>AddDelegate<\/b>, <b>AddEnum<\/b>, <b>AddFunction<\/b>, <b>AddImplementedInterface<\/b>, <b>AddProperty<\/b>, <b>AddStruct <\/b>oder <b>AddVariable<\/b>, um die entsprechenden Elemente zu einer Klasse hinzuzuf&uuml;gen. Darunter sind Methoden wie <b>AddImplementedInterface <\/b>oder <b>AddProperty<\/b>, die nicht f&uuml;r das <b>FileCodeModel<\/b>-Objekt bereitstehen.<\/p>\n<p>In den folgenden Abschnitten erl&auml;utern wir die Methoden mal f&uuml;r das <b>FileCodeModel<\/b>-Objekt und mal f&uuml;r das <b>CodeClass<\/b>-Objekt.<\/p>\n<h2>Attribut hinzuf&uuml;gen mit AddAttribute<\/h2>\n<p>Mit der folgenden Anweisung f&uuml;gen wir ein neues Attribut zu einem <b>FileCodeModel <\/b>hinzu:<\/p>\n<pre>objFileCodeModel.AddAttribute(\"NeuesAttribut\",\"Wert\")<\/pre>\n<p>Der Code in der Datei <b>NeueKlasse.vb <\/b>sieht danach wie folgt aus:<\/p>\n<pre>&lt;Assembly: NeuesAttribut(Wert)&gt;\r\n<span style=\"color:blue;\">Public Class<\/span> NeueKlasse\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<h2>Hinzuf&uuml;gen einer Klasse mit AddClass<\/h2>\n<p>Mit der Methode <b>AddClass <\/b>und mindestens dem Klassennamen als Parameter f&uuml;gen Sie eine neue Klasse hinzu:<\/p>\n<pre>objFileCodeModel.AddClass(\"WeitereKlasse\")<\/pre>\n<p>Das Ergebnis mit diesem einfachen Aufruf sieht so aus:<\/p>\n<pre><span style=\"color:blue;\">Public Class<\/span> NeueKlasse\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Sie k&ouml;nnen allerdings noch einige weitere Parameter nutzen. <\/p>\n<ul>\n<li><b>Position<\/b>: Der Parameter <b>Position <\/b>gibt an, an welcher Position die neue Klasse erstellt werden soll. Hier k&ouml;nnen Sie einen Verweis auf das Code-Element angeben, hinter dem das neue Element positioniert werden soll. Oder Sie geben den Index f&uuml;r die Position an, wobei <b>0 <\/b>der ersten Position, <b>-1 <\/b>der letzten Position und alle anderen Werte die Position hinter dem vorhandenen Element mit dem angegebenen Index bedeuten. Die folgenden Anweisungen platzieren die Klassen in der Reihenfolge <b>NullteKlasse<\/b>, <b>ErsteKlasse<\/b>, <b>ZweiteKlasse <\/b>und <b>DritteKlasse<\/b> im Code:<\/li>\n<\/ul>\n<pre>         objClass = objFileCodeModel.AddClass(\"ErsteKlasse\")\r\n         objFileCodeModel.AddClass(\"DritteKlasse\", objClass)\r\n         objFileCodeModel.AddClass(\"ZweiteKlasse\", objClass)\r\n         objFileCodeModel.AddClass(\"NullteKlasse\", 0)<\/pre>\n<ul>\n<li><b>Bases<\/b>: Klassen, von denen die Klasse erben soll. Dabei k&ouml;nnen Sie den Namen der Basisklasse oder auch ein Objekt angeben:<\/li>\n<\/ul>\n<pre>         ''Beispiel 1:\r\n         objFileCodeModel.AddClass(\"KlasseMitBase\",,\"Basisklasse\")\r\n         ''Liefert folgende Klasse:\r\n         <span style=\"color:blue;\">Public <\/span>Class KlasseMitBase\r\n             Inherits Basisklasse\r\n         End Class\r\n         ''Aufbauend auf dem ersten Beispiel:\r\n         objFileCodeModel.AddClass(\"KlasseMitBase2\", , objClass)\r\n         ''Liefert folgende Klasse:\r\n         <span style=\"color:blue;\">Public <\/span>Class KlasseMitBase2\r\n             Inherits KlasseMitBase\r\n         End Class<\/pre>\n<ul>\n<li><b>ImplementedInterfaces<\/b>: Klassen, die Interfaces implementieren. F&uuml;r Beispielzwecke greifen wir schon der Methode zum Erstellen von Interfaces vor. Dabei erstellen wir zuerst mit <b>AddInterface <\/b>ein <b>Interface<\/b>-Element und referenzieren dieses in der folgenden <b>AddClass<\/b>-Methode gleich zwei Mal &#8211; einmal, damit die Klasse hinter dem Interface angelegt wir und einmal, damit sie das Interface implementiert:<\/li>\n<\/ul>\n<pre>         ''Beispiel:\r\n         objInterface = objFileCodeModel.AddInterface(\"Interface\")\r\n         objClass = objFileCodeModel.AddClass(\"KlasseMitInterface\", objInterface, , objInterface)\r\n        ''Liefert folgende Elemente:\r\n         <span style=\"color:blue;\">Public <\/span>Interface [Interface]\r\n         End Interface\r\n         <span style=\"color:blue;\">Public <\/span>Class KlasseMitInterface\r\n            Implements [Interface]\r\n         End Class<\/pre>\n<ul>\n<li><b>Access<\/b>: Gibt die Zugriffsrechte auf die Klasse an. Standardm&auml;&szlig;ig kommt hier <b>Public <\/b>zum Einsatz, was der Konstanten <b>vs-CM-AccessPublic <\/b>entspricht. Die &uuml;brigen Konstanten finden Sie in den folgenden Beispielen, die Ergebnisse in Bild 1:<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_04\/pic_188_001.png\" alt=\"Verschiedene Klassen\" width=\"424,7115\" height=\"337,2173\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Verschiedene Klassen<\/span><\/b><\/p>\n<\/ul>\n<pre>         ''Beispiele f&uuml;r verschiedene Zugriffsrechte:\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_Default\", , , , EnvDTE.vsCMAccess.vsCMAccessDefault)\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_Private\", , , , EnvDTE.vsCMAccess.vsCMAccessPrivate)\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_Project\", , , , EnvDTE.vsCMAccess.vsCMAccessProject)\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_ProjectOrProtected\", , , , _\r\n             EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected)\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_Protected\", , , , EnvDTE.vsCMAccess.vsCMAccessProtected)\r\n         objClass = objFileCodeModel.AddClass(\"Klasse_Public\", , , , EnvDTE.vsCMAccess.vsCMAccessPublic)<\/pre>\n<h2>Code-Elemente als Objekt<\/h2>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000188\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000188?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000188\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"29a9ab4ae1\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Beitrag &#8220;Visual Studio mit LINQPad: Project und ProjectItems&#8221; haben wir uns angesehen, wie Sie per Code auf Project-, Solution- und ProjectItem-Elemente zugreifen. Nun wollen wir uns den Umgang mit den ProjectItem-Objekten ansehen und herausfinden, wie wir beispielsweise den enthaltenen Code manipulieren k&ouml;nnen und Klassen, Prozeduren und Variablen anzulegen. Dazu ben&ouml;tigen wir einen Verweis auf das FileCodeModel-Objekt des jeweiligen ProjectItem-Elements. Wie wir das holen und was wir damit anstellen k&ouml;nnen, zeigt der vorliegende Artikel.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662019,66042019,44000013],"tags":[],"yst_prominent_words":[],"class_list":["post-55000188","post","type-post","status-publish","format-standard","hentry","category-662019","category-66042019","category-Visual_Studio_nutzen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000188"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000188\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000188"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}