Extending Intellisense: Namespace lookup with a macro
Namespaces in .NET are great! But how many times do you find yourself typing "Private r As xmlreader", and then noticing that there is no Imports/using statement for the System.Xml Namespace? Then you would have to scroll to the top of your document and add the Imports/using statement by hand. Alternatively you could choose to add the namespace to your declaration: "Private r As System.Xml.XmlReader". Since we are all developers, why not develop something to help developers with this tedious task of namespace lookups?
I've created the macro below that does the namespace lookup trick. The macro has 3 public methods you can assign for example to a shortcut key:
- AddNamespace
This method will search the corresponding namespace for the typename you've just typed in your code, and add it to your type. So if you type for example "textreader", the macro will convert it to "System.IO.TextReader". - AddImports
This method will search the corresponding namespace for the typename you've just typed in your code and add an Imports statement at the top of your code. So, if you've typed "textreader", the marco will add "Imports System.IO" at the top of your code. Additionaly the "textreader" will by replaced by "TextReader". - AddUsing
This method is the same as the AddImports method, but can be used for the C# "using" keyword.
Since this is the first version of the macro, I would appriciate if you can give some feedback if you find it usefull, or if there are any bugs/problems! Here is the complete source code (I suggest you create a new macro module for it, and call it TypeFinder):
Imports EnvDTE
Imports System.Diagnostics
Imports System
Public Module TypeFinder
Private Function SearchTypeInAssembly(ByVal typename As String, ByVal ass As Reflection.Assembly)
DTE.StatusBar.Text = "Searching for '" & typename & "' " & ass.GetName.Name & "..."
Dim t As Type
For Each t In ass.GetTypes
If t.Name.ToLower = typename Then
Return t
End If
Next
End Function
Private Function SearchType(ByVal typename As String) As Type
typename = typename.ToLower
Dim projs As System.Array = DTE.ActiveSolutionProjects
Dim ass As Reflection.Assembly = Reflection.Assembly.LoadWithPartialName("mscorlib")
Dim t As Type = SearchTypeInAssembly(typename, ass)
If Not t Is Nothing Then Return t
Dim proj As Project
For Each proj In projs
Dim o As VSLangProj.VSProject = proj.Object
Dim ref As VSLangProj.Reference
For Each ref In o.References
ass = Reflection.Assembly.LoadFile(ref.Path)
t = SearchTypeInAssembly(typename, ass)
If Not t Is Nothing Then Return t
Next
Next
DTE.StatusBar.Text = "Could not find type '" & typename & "' in the referenced libraries."
DTE.StatusBar.Highlight(True)
Return Nothing
End Function
Public Sub AddNamespace()
Dim text As TextSelection = DTE.ActiveDocument.Selection
text.WordLeft(True)
Dim t As Type = SearchType(text.Text)
If Not t Is Nothing Then
text.Text = t.FullName
text.EndOfLine()
DTE.StatusBar.Text = "Ready"
End If
End Sub
Public Sub AddImports()
Dim text As TextSelection = DTE.ActiveDocument.Selection
text.WordLeft(True)
Dim t As Type = SearchType(text.Text)
If Not t Is Nothing Then
Dim line As Integer = text.AnchorPoint.Line
text.Text = t.Name
text.StartOfDocument()
text.Insert("Imports " & t.Namespace & vbCrLf)
text.MoveToLineAndOffset(line + 1, 1)
text.EndOfLine()
DTE.StatusBar.Text = "'Imports " & t.Namespace & "' added to the document."
DTE.StatusBar.Highlight(True)
End If
End Sub
Public Sub AddUsing()
Dim text As TextSelection = DTE.ActiveDocument.Selection
text.WordLeft(True)
Dim t As Type = SearchType(text.Text)
If Not t Is Nothing Then
Dim line As Integer = text.AnchorPoint.Line
text.Text = t.Name
text.StartOfDocument()
text.Insert("using " & t.Namespace & ";" & vbCrLf)
text.MoveToLineAndOffset(line + 1, 1)
text.EndOfLine()
DTE.StatusBar.Text = "'using " & t.Namespace & ";' added to the document."
DTE.StatusBar.Highlight(True)
End If
End Sub
End Module