Visual Studio Hacks [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Visual Studio Hacks [Electronic resources] - نسخه متنی

Andrew Lockhart

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Hack 56. Automatically Add using and Imports Statements

Use a macro to scan your code and determine
which namespaces need to be imported.


The .NET Framework is built around
namespaces. Every class in the .NET
Framework belongs to a namespace; you need to tell the compiler that
you want to use the classes in that namespace. This is done through
the use of a using
statement in C# or an
Imports statement in VB.NET. One of the annoyances
that this creates is then realizing that you have not added a
using or Imports statement for
a class that you added. This means you have to find out what
namespace you need to add for this class and then go to the top of
your document and add the name of the namespace. Alternatively, you
could fully qualify the class you are using, meaning that you prefix
the name of the class with the full name of the namespace (e.g.,
System.Data.SqlClient.SqlConnection).

A set of macros that will do either of these for you automatically is
available. The first macro is called AddDirective and will look for your class
and then add the Imports or
using statement for you. To use this macro, you
simply need to highlight the name of your class and then run the
AddDirective macro. If you highlight SqlConnection
and run the macro, it will add using
System.Data.SqlClient;
or Imports
System.Data.SqlClient
to the top of your document.

The other macro is called AddNamespace and will, instead of adding
a using or Imports statement,
fully qualify the name of your class. If
you highlight SqlConnection and run the macro, it
will add System.Data.SqlClient to the front of
your class.

The macro works by cycling through all the assemblies referenced by
your project. If it finds a class in multiple namespaces, the first
namespace found is used.

This macro was written by a developer named Jan Tielens, and its code
is shown here (this one is pretty long; you may want to download it
from the book site):

'TypeFinder Macro, version 2.11
'For Visual Studio.NET
'By Jan Tielens, http://weblogs.asp.NET/jan
'With the help of:
'- Yves Hanoulle, http://www.hanoulle.be/
'- Thomas Freudenberg
'- Guillaume Roberge
Imports EnvDTE
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection
Imports System.IO
Public Module TypeFinder
Private Class TypeCache
Public Shared Cache As Hashtable = New Hashtable
End Class
Private Function SearchTypeInAssembly( _
ByVal typename As String, _
ByVal assm As Reflection.Assembly) As Type
DTE.StatusBar.Text = "Searching for '" & _
typename & "' " & assm.GetName.Name & "..."
If (Not TypeCache.Cache.ContainsKey(typename)) Then
Dim t As Type
For Each t In assm.GetTypes
If t.Name.ToLower = typename Then
TypeCache.Cache.Add(typename, t)
Return t
End If
Next
Else
Return TypeCache.Cache.Item(typename)
End If
End Function
Private Function SearchType(ByVal typename As String) As Type
typename = _
typename.ToLower.Trim.Replace(";", ").Replace(".", ")
Dim assm As [Assembly]
Dim currentAssm As String
Dim currentPath As String
Dim t As Type
Dim p As [Property]
'search in principal assembly
assm = Reflection.Assembly.LoadWithPartialName("mscorlib")
t = SearchTypeInAssembly(typename, assm)
If Not t Is Nothing Then Return t
'search in assemblies in solutions
Dim proj As Project
For Each proj In DTE.ActiveSolutionProjects
'search in references of current project
Dim ref As VSLangProj.Reference
For Each ref In proj.Object.References
assm = Reflection.Assembly.LoadFrom(ref.Path)
t = SearchTypeInAssembly(typename, assm)
If Not t Is Nothing Then Return t
Next
currentAssm = "
currentPath = "
'obtain properties to get assembly
'associated with project
For Each p In proj.Properties
If (p.Name = "OutputFileName") Then
currentAssm = p.Value
ElseIf (p.Name = "LocalPath") Then
currentPath = p.Value
End If
If currentAssm.Length > 0 _
And currentPath.Length > 0 Then Exit For
Next
'search in the assembly associated with the project
currentAssm = currentPath + "bin\" + _
DTE.Solution.SolutionBuild.ActiveConfiguration.Name _
+ "\" + currentAssm
Dim tempAss As String = currentAssm + "2"
Try
Try
If (File.Exists(tempAss)) Then
File.Delete(tempAss)
End If
Catch
End Try
'we copy the assembly to be sure that when the
'compilation will be launch the file
'could be written
File.Copy(currentAssm, tempAss)
assm = Reflection.Assembly.LoadFrom(tempAss)
t = SearchTypeInAssembly(typename, assm)
Try
File.Delete(tempAss)
Catch
End Try
If Not t Is Nothing Then Return t
Catch ex As Exception
End Try
Next
DTE.StatusBar.Text = "Could not find type '" _
& typename & "'"
DTE.StatusBar.Highlight(True)
Return Nothing
End Function
Public Sub AddNamespace( )
Dim text As TextSelection = DTE.ActiveDocument.Selection
If (text.Text.Length = 0) Then 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 AddDirective( )
Dim text As TextSelection = DTE.ActiveDocument.Selection
If (text.Text.Length = 0) Then text.WordLeft(True)
Dim t As Type = SearchType(text.Text)
If Not t Is Nothing Then
Dim keyword, suffix As String
Dim line As Integer = text.AnchorPoint.Line
text.Text = t.Name
Select Case DTE.ActiveDocument.Language
Case "CSharp"
keyword = "using"
suffix = ";"
Case "Basic"
keyword = "Imports"
suffix = String.Empty
Case Else
Throw New System.Exception("Invalid Language: " _
& DTE.ActiveDocument.Language)
End Select
Dim alreadyUsed As Boolean = False
text.StartOfDocument( )
'Skip the headers
text.WordRight(True, 2)
While text.Text.StartsWith("/*") _
Or text.Text.StartsWith(" *") _
Or text.Text.StartsWith("//") _
Or text.Text.StartsWith("'")
text.LineDown( )
text.StartOfLine( )
text.WordRight(True, 2)
End While
text.StartOfLine( )
text.WordRight(True)
Dim lineTarget As Integer = text.AnchorPoint.Line
Dim correctPlace As Boolean = False
While text.Text.StartsWith(keyword) And _
Not alreadyUsed And Not correctPlace
Dim startpt As EditPoint = text.BottomPoint.CreateEditPoint( )
Dim endpt As EditPoint = text.BottomPoint.CreateEditPoint( )
endpt.EndOfLine( )
If DTE.ActiveDocument.Language = "CSharp" Then
'Skip ';'
endpt.CharLeft( )
End If
Dim currentText As String = endpt.GetText(startpt)
If currentText = t.Namespace Then
alreadyUsed = True
ElseIf (currentText < t.Namespace) Then
text.LineDown( )
text.StartOfLine( )
text.WordRight(True)
Else
correctPlace = True
lineTarget = text.AnchorPoint.Line
End If
End While
text.StartOfLine( )
If alreadyUsed Then
DTE.StatusBar.Text = "Namespace " & t.Namespace _
& " is already imported."
DTE.StatusBar.Highlight(True)
text.MoveToLineAndOffset(line, 1)
Else
If (correctPlace) Then text.GotoLine(lineTarget)
DTE.UndoContext.Open("Add Namespace Directive")
text.Insert(keyword & " " & t.Namespace _
& suffix & vbCrLf)
DTE.UndoContext.Close( )
DTE.StatusBar.Text = "'" & keyword & " " _
& t.Namespace _
& suffix & "' added to the document."
DTE.StatusBar.Highlight(True)
text.MoveToLineAndOffset(line + 1, 1)
End If
text.EndOfLine( )
End If
End Sub
End Module

All you need to do is download or transcribe this code into the Macro
IDE [Hack #51] . You will then
see the two macros in the Macro Explorer and can start using them
right
away.


/ 172