Freigeben über


Ermitteln von Code über das Codemodell (Visual Basic)

Add-Ins für Visual Studio sind in Visual Studio 2013 veraltet. Sie müssen für Ihre Add-Ins ein Upgrade auf VSPackage-Erweiterungen durchführen. Weitere Informationen über das Durchführen eines Upgrades finden Sie unter FAQ: Konvertieren von Add-Ins in VSPackage-Erweiterungen.

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#)

Visual C++-Codemodell

Diagramm "Automationsobjektmodell"

Visual C++-Codemodell

Weitere Ressourcen

Erstellen und Steuern von Umgebungsfenstern

Erstellen von Add-Ins und Assistenten

Referenz zur Automatisierung und Erweiterbarkeit