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 |