Ermitteln von Code über das Codemodell (Visual Basic)
Durch das Codemodell von Visual Studio können Automatisierungsclients Codedefinitionen in einem Projekt ermitteln und diese Codeelemente ändern. Bei jeder Änderungen im Code-Editor aktualisiert das Codemodell automatisch alle Objekte, auf die zuvor verwiesen wurde.Wenn Sie beispielsweise auf ein Klassenobjekt verweisen und ein Benutzer zu einem späteren Zeitpunkt eine neue Funktion hinzufügt, wird diese bei den Membern aufgelistet.Durch das Codemodell erübrigt es sich für Automatisierungsclients, einen Parser für Visual Studio-Sprachen zu implementieren, um in einem Projekt Definitionen auf höheren Ebenen wie Klassen, Schnittstellen, Strukturen, Methoden, Eigenschaften usw. ermitteln zu können.
Das Hauptcodemodell von Visual Studio vermeidet sprachspezifische Codebereiche und stellt daher z. B. auch kein Objektmodell für Funktionsanweisungen oder vollständige Angaben zu Parametern bereit.Parameterangaben umfassen lediglich den jeweiligen Typ und Namen. Weitere Informationen, ob es sich z. B. um Eingabe-, Ausgabe- oder optionale Parameter handelt, sind nicht verfügbar.Visual C++ stellt eine erweiterte Version des Hauptcodemodells bereit, das für Visual C++-Projekte verwendet wird.Weitere Informationen hierzu finden Sie unter Visual C++-Codemodell.
Überprüfen und Bearbeiten von Code mit dem Codemodell
Das Codemodell ist primär textbasiert, d. h. das Programm oder der Code im Projekt werden in Textdateien gespeichert.Die Suche nach einem Projektcode erfolgt mithilfe des Projektmodells, mit dem Sie zu jedem Projektelement gelangen. Durch Anwendung von FileCodeModel können Sie überprüfen, ob ein Projektelement Code enthält.Sind Codeelemente in einem Projektelement enthalten, können diese Objekte vom Editor zurückgeben. Das Automatisierungsmodell des Text-Editors wird vom Codemodell verwendet, um Code zu ändern oder lokalisierte Analysen durchzuführen.Mithilfe des Editor-Objektmodells können Sie das Codeelement anfordern, das die Einfügemarke des Editors enthält, oder Sie können ein TextPoint-Objekt auf Funktions- oder Klassenebene anfordern.
Der primäre Einstiegspunkt in das Hauptcodemodell von Visual Studio ist das CodeModel-Objekt. Im Codemodell wird an mehreren Stellen eine allgemeine CodeElements-Auflistung verwendet.Eine Auflistung befindet sich auf der CodeElements-Ebene, eine weitere auf der Klassen- oder Schnittstellenebene, die die Member dieser Objekte zurückgibt.Jedes Element einer CodeElements-Auflistung ist ein CodeElement2-Objekt. Jedes CodeElement2-Objekt verfügt über eine Kind-Eigenschaft zur Identifizierung des Typs, z. B. Klasse, Schnittstelle, Struktur, Funktion, Eigenschaft, Variable usw.
Sprachspezifische Codemodelle
Visual C++ stellt eine Erweiterung für das Hauptcodemodell zur Verwendung von Visual C++-spezifischem Code bereit.Wird beispielsweise durch Language angezeigt, dass das jeweilige Codeelement ein Objekt für das Visual C++-Codemodell ist und Kind = vsCMElementClass gegeben ist, können Sie entweder QueryInterface (QI) für CodeClass aus dem Visual Studio-Codemodell oder QI für VCCodeClass aus dem sprachspezifischen Visual C++-Codemodell auswählen.Weitere Informationen zum spezifischen Codemodell von Visual C++ finden Sie unter Gewusst wie: Bearbeiten von Code mit dem Visual C++-Codemodell (Visual Basic) und Visual C++-Codemodell
Hinweise zum Hauptcodemodell von Visual Studio
Eine sprachspezifische Gestaltung der Sprachimplementierungen von Microsoft ist nur mit der Implementierung des Codemodells von Visual C++ möglich.
In den Implementierungen einiger Sprachen wird nicht das vollständige Visual Studio-Codemodell implementiert. Hilfethemen weisen ggf. auf Ausnahmen hin.Die meisten Unterschiede zwischen den Codemodellimplementierungen sind auf funktionale Besonderheiten der einzelnen Sprachen zurückzuführen.So ist es beispielsweise nicht möglich, CodeNamespace-Objekten in Visual Basic oder Visual C# Funktionen hinzuzufügen, da nur Visual C++ über Funktionsdefinitionen höchster Ebene verfügt.
Beschreibung
Dieses Add-In stellt exemplarisch die verschiedenen Codeelemente einer Visual Studio-Datei vor.Um dieses Beispiel ausführen zu können, muss im Visual Studio-Code-Editor eine Quellcodedatei geöffnet sein. Informationen zum Ausführen der Beispiele finden Sie unter Gewusst wie: Kompilieren und Ausführen der Codebeispiele für das Automatisierungsobjektmodell.
Code
' Add-in code.
Public Sub OnConnection(ByVal application As Object, ByVal _
connectMode As ext_ConnectMode, ByVal addInInst As Object, _
ByRef custom As Array) Implements IDTExtensibility2.OnConnection
_applicationObject = CType(application, DTE2)
_addInInstance = CType(addInInst, AddIn)
' Pass the applicationObject member variable to the code example.
OutlineCode(_applicationObject)
End Sub
Sub OutlineCode(ByVal dte As DTE2)
Dim fileCM As FileCodeModel2 _
= CType(dte.ActiveDocument.ProjectItem.FileCodeModel, _
FileCodeModel2)
Dim elts As CodeElements
elts = fileCM.CodeElements
Dim elt As CodeElement2
Dim i As Integer
MsgBox("About to walk top-level elements ...")
For i = 1 To fileCM.CodeElements.Count
elt = CType(elts.Item(i), CodeElement2)
CollapseElt(elt, elts, i)
Next
End Sub
Sub CollapseElt(ByVal elt As CodeElement2, ByVal elts As _
CodeElements, ByVal loc As Long)
Dim epStart As EditPoint2
Dim epEnd As EditPoint2
epStart = CType(elt.StartPoint.CreateEditPoint, EditPoint2)
' Do this since we move it later.
epEnd = CType(elt.EndPoint.CreateEditPoint, EditPoint2)
epStart.EndOfLine()
If ((elt.IsCodeType) And (elt.Kind <> _
vsCMElement.vsCMElementDelegate)) Then
MsgBox("Got type but not a delegate, named : " & elt.Name)
Dim ct As CodeType
ct = CType(elt, CodeType)
Dim mems As CodeElements
mems = ct.Members
MsgBox("Set mems = ct.members")
Dim i As Integer
For i = 1 To ct.Members.Count
CollapseElt(CType(mems.Item(i), CodeElement2), mems, i)
Next
ElseIf (elt.Kind = vsCMElement.vsCMElementNamespace) Then
MsgBox("Got a namespace, named: " & elt.Name)
Dim cns As CodeNamespace
cns = CType(elt, CodeNamespace)
MsgBox("set cns = elt, named: " & cns.Name)
Dim mems_vb As CodeElements
mems_vb = cns.Members
MsgBox("Got cns.members")
Dim i As Integer
For i = 1 To cns.Members.Count
CollapseElt(CType(mems_vb.Item(i), CodeElement2), _
mems_vb, i)
Next
End If
End Sub
Änderungsverhalten von Codemodellelementwerten
Die zugeordneten Werte von Codemodellelementen (z. B. Klassen, Strukturen, Funktionen, Attribute, Delegaten usw.) können sich nach bestimmen Bearbeitungsvorgängen ändern.Sie können daher nicht davon ausgehen, dass die Werte statisch bleiben.
Wenn Sie beispielsweise einer lokalen Variablen ein Codemodellelement zuordnen und dann einen Eigenschaftswert für diese lokale Variable festlegen, enthält die lokale Variable möglicherweise kein gültiges Codemodellelement, wenn Sie später auf sie verweisen.Tatsächlich kann sie sogar ein anderes Codemodellelement enthalten.
Sie sollten eine Klasse mit der Funktion "MyFunction" verwenden, die einer CodeFunction-Variablen zugeordnet ist. Dann wird die Name-Eigenschaft der CodeFunction auf den Wert "YourFunction" festgelegt. Nach dieser Variablenzuordnung ist nicht mehr sichergestellt, dass die lokale Variable dieselbe CodeFunction darstellt.Anschließend wird beim Zugreifen auf den Wert der Eigenschaft möglicherweise E_FAIL als Ergebnis zurückgegeben.
Als Vorgehensweise in dieser Situation wird empfohlen, die lokale Variable explizit dem richtigen Codemodellelement zuzuordnen, bevor auf die Eigenschaftswerte zugegriffen wird.Im Folgenden ein Beispiel für diese Vorgehensweise.(Der Code liegt als Add-In vor.)
Beschreibung
In diesem Add-In wird die richtige Vorgehensweise beim Zugreifen auf Werte für CodeElements veranschaulicht, sodass der richtige Wert abgerufen wird.Informationen zum Ausführen der Beispiele finden Sie unter Gewusst wie: Kompilieren und Ausführen der Codebeispiele für das Automatisierungsobjektmodell.
Code
[Visual Basic]
Public Sub OnConnection(ByVal application As Object, ByVal _
connectMode As ext_ConnectMode, ByVal addInInst As Object, _
ByRef custom As Array) Implements IDTExtensibility2.OnConnection
_applicationObject = CType(application, DTE2)
_addInInstance = CType(addInInst, AddIn)
ReassignValue(_applicationObject)
End Sub
Sub ReassignValue(ByVal dte As DTE2)
' Before running, create a new Windows application project,
' and then add a function to it named MyFunction.
Try
Dim myFCM As FileCodeModel = _
dte.ActiveDocument.ProjectItem.FileCodeModel
' Change the MyFunction name in Form1 class to
' the name, OtherFunction.
Dim myClass1 As CodeClass = _
CType(myFCM.CodeElements.Item("Form1"), CodeClass2)
Dim myFunction As CodeFunction = _
CType(myClass1.Members.Item("MyFunction"), CodeFunction2)
myFunction.Name = "OtherFunction"
myFunction = CType(myClass1.Members.Item("OtherFunction"), _
CodeFunction2)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
[C#]
public void OnConnection(object application, ext_ConnectMode
connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
ReassignValue(_applicationObject);
}
// Before running, create a new Windows application project,
// and then add a function to it named MyFunction.
public void ReassignValue(DTE2 dte)
{
try
{
FileCodeModel myFCM =
dte.ActiveDocument.ProjectItem.FileCodeModel;
// Change the MyFunction name in Form1 class to
// the name, OtherFunction.
CodeClass myClass1 =
(CodeClass2)myFCM.CodeElements.Item("Form1");
CodeFunction myFunction =
(CodeFunction2)myClass1.Members.Item("MyFunction");
myFunction.Name = "OtherFunction";
myFunction =
(CodeFunction2)myClass1.Members.Item("OtherFunction");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
Hinweis |
---|
Wenn Sie die Eigenschaften von untergeordneten Elementen des Codemodellelements festlegen, tritt dieses Verhalten nicht auf.Nur Eigenschaften, die CodeElement direkt betreffen (z. B. der Name des Elements, der Typ einer Funktion, die Signatur einer Methode usw.)weisen dieses nicht deterministische Verhalten auf. Dieses Beispiel funktioniert zudem nur, wenn der neue Name des CodeElement unter den gleichgestellten Elementen eindeutig ist.Der Grund dafür ist, dass die Item-Eigenschaft die erste Übereinstimmung zurückgibt. Dies funktioniert nicht für überladene Methoden bzw. Eigenschaften, partielle Klassen oder Namespaces mit demselben Namen. |
Siehe auch
Aufgaben
Gewusst wie: Kompilieren von Beispielcode für die Erweiterbarkeit des Visual C++-Codemodells
Gewusst wie: Erstellen von Add-Ins
Exemplarische Vorgehensweise: Erstellen eines Assistenten
Gewusst wie: Bearbeiten von Code mit dem Visual C++-Codemodell (Visual C#)
Konzepte
Ermitteln von Code über das Codemodell (Visual C#)
Diagramm "Automationsobjektmodell"
Weitere Ressourcen
Erstellen und Steuern von Umgebungsfenstern