Using the FileCodeModel to Get the Code for a MethodUsed in Conject with the CodeModel Object | | Using the CodeModel object, you can explore a project or solution in Visual Studio .NET. The projects can be VB.NET or CSharp (C#), and can be mixed and the CodeModel object can be used to explore them. Given that you have retrieved a desired method name and its length from using th CodeModel object, how can you fetch the code for that method?
The GetCodeForMethod, shown below, assumes that you have retrieved a ProjectItem and starting and ending line numbers by using the CodeModel object. These parameters are passed into the method. The method returns a string which contains the code, along with any comments that precede the code for the method.
This code will retrieve code from a C# or VB CodeClass. C# code will always have a Namespace. The VB Class can be with or without Namespaces.
Since the method is lengty, I will document the code with in-line comments rather than trying to describe it from outside of the method.
Function GetCodeForMethod(ByRef roPI As ProjectItem, _
ByVal iStPt As Integer, _
Optional ByVal iEndPt As Integer = 1) _
As String
' returns code for a module which is pointed
' to by projectitem, start and end pts.
' handles VB and C#, with/without namespaces.
Dim pi As ProjectItem = roPI
Dim filecm As FileCodeModel = pi.FileCodeModel
Dim ce As CodeElement
Dim i As Integer
Try
' If there are no codeelements in the projectitem, exit
' leaving the string empty...
If filecm.CodeElements.Count = 0 Then return String.Empty
' a code module or class consists of code elements, which
' are methods, variables, namespaces, etc.
For Each ce In filecm.CodeElements
' first, check to see if we have a namespace wrapping
' one or more classes
If ce.Kind = vsCMElement.vsCMElementNamespace Then
Dim cns As CodeNamespace = ce
Dim cl As CodeClass
' a namespace can have one or more classes
For Each cl In cns.Members
Dim cetype As CodeType = CType(cl, CodeType)
' the editpoint object is used to walk thru the
' code buffer that lives behind text window,
' regardless of whether the window is open or not
' here we move to the begining of the code element
Dim ep As EditPoint = _
cetype.GetStartPoint _
(vsCMPart.vsCMPartHeader).CreateEditPoint
Dim sTextLine As String
Dim sb As New Text.StringBuilder()
ep.MoveToLineAndOffset(iStPt, 1)
' back up to previous line looking for
' preceding comments
Do
ep.LineUp()
iStPt -= 1
iEndPt += 1
sTextLine = ep.GetText(ep.LineLength)
If sTextLine.Trim.Length = 0 OrElse _
(Not sTextLine.trim.StartsWith("'") And _
Not stextline.Trim.StartsWith("/")) Then
ep.LineDown()
iStPt += 1
iEndPt -= 1
Exit Do
End If
Loop
' loop to get all lines in the method
' use for instead of do so c# will work
For i = 1 To iEndPt 'Do
sTextLine = ep.GetText(ep.LineLength)
sb.Append(sTextLine & vbCrLf)
ep.LineDown()
Next i 'Loop
Return sb.ToString
Next
Else
' first, check to see if we have a namespace wrapping
' one or more classes
Dim celt As CodeElement = ce
Dim cetype As CodeType = CType(celt, CodeType)
' the editpoint object is used to walk thru the
' code buffer that lives behind text window,
' regardless of whether the window is open or not
' here we move to the begining of the code element
Dim ep As EditPoint = _
cetype.GetStartPoint(vsCMPart.vsCMPartHeader) _
.CreateEditPoint
Dim sTextLine As String
Dim sb As New Text.StringBuilder()
ep.MoveToLineAndOffset(iStPt, 1)
' back up to previous line looking for
' preceding comments
Do
ep.LineUp()
iStPt -= 1
iEndPt += 1
sTextLine = ep.GetText(ep.LineLength)
If sTextLine.Trim.Length = 0 OrElse _
(Not sTextLine.trim.StartsWith("'") And _
Not stextline.Trim.StartsWith("/")) Then
ep.LineDown()
iStPt += 1
iEndPt -= 1
Exit Do
End If
Loop
' loop to get all lines in the method
' use for instead of do so c# will work
For i = 1 To iEndPt 'Do
sTextLine = ep.GetText(ep.LineLength)
sb.Append(sTextLine & vbCrLf)
ep.LineDown()
Next i 'Loop
Return sb.ToString
End If
Next
Catch ex As System.Exception
MsgBox("Error in CFileCodelModel.GetCodeForMethod: " & ex.Message)
End Try
End Function
| |