lunes, 1 de diciembre de 2008

Convertir un campo público a propiedad Visual Studio - VB y C#

Cómo hacer para convertir automáticamente un campo (variable) a una propiedad pública y utilizarlo con una combinación de teclas en el Visual Studio 2008.

La idea es crear una macro que se encargue de hacer la conversión de la línea actual de código donde estemos parados y poder ejecutar esta macro con alguna combinación de teclas.

Por ejemplo, queremos convertir esta línea:
Public id As Integer

En esto:
Private _id As Integer
Public Property id() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
NOTA: En Visual Studio 2010 será mucho más simple la declaración de propiedades en VB, pareciéndose más a la declaración en C#

Lo primero que se necesita es abrir el explorador de macros (Menú View, Other Windows, Macro Explorer) o bien con ALT+F8.
En la nueva ventana, hacer click derecho en MyMacros y seleccionar "New Module", ponerle como nombre thepirat, y nuevamente click derecho (ahora sobre el nuevo módulo recién creado) y seleccionar "New Macro".
A continuación aparecerá el editor de macros y estaremos situados dentro de un método que seguramente se llama Sub Macro1() adentro del módulo llamado thepirat.

Adentro de este módulo, copiar y reemplazar TODO el código por el siguiente código
 

'The-Pirat 2008
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Text.RegularExpressions

'http://msdn.microsoft.com/en-us/library/envdte.textselection_members.aspx

Public Module thepirat
'Declaro la expresión regular
Private Const REGEX_Declaracion_VB As String = _
"(public|private|dim)\s+(?'var'\w+)\s+as\s+(?'tipo'.*)"
Private Const REGEX_Declaracion_CSHARP As String = _
"(public\s|private\s|internal\s)?(?'tipo'.+)\s+(?'var'\w+)\s*;"

''' <summary>
''' Convierte un campo en propiedad pública.
''' Acepta la forma: Dim variable as tipo, public v as t, private v as t
''' </summary>
''' <remarks></remarks>
Public Sub campo2prop()
'Creo un punto de UNDO
DTE.UndoContext.Open("UndoCampoPropiedad")
Try
'Obtengo el documento activo
Dim doc = CType(DTE.ActiveDocument, EnvDTE.Document)
'Obtengo la selección del documento activo
Dim ts As TextSelection = doc.Selection
'Selecciono la línea completa
ts.SelectLine()
'Determino si es VB o C#
Dim bVB As Boolean = EsVisualBasic(doc.Name)
'Obtengo el texto de la selección (la línea)
Dim sLinea As String = ts.Text.Trim()
'Obtengo el nombre de la variable y su tipo
Dim sVar As String = "", sTipo As String = ""
ObtenerVariableYtipo(bVB, sLinea, sVar, sTipo)
'Si fue exitoso, imprimo la propiedad
ts.Insert(DevolverPropiedad(bVB, sVar, sTipo))
Catch ex As Exception
MsgBox(ex.Message)
Finally
'Cierro el punto de UNDO
DTE.UndoContext.Close()
End Try
End Sub

'Determina si es VB o C#
Private Function EsVisualBasic(ByVal nombre As String) As Boolean
If (nombre.EndsWith(".cs") Or nombre.EndsWith(".cpp") Or nombre.EndsWith(".h") Or nombre.EndsWith(".idl") Or nombre.EndsWith(".jsl")) Then
Return False
ElseIf (nombre.EndsWith(".vb")) Then
Return True
Else
Throw New Exception("Tipo de archivo irreconocible")
End If
End Function

'Devuelve el nombre de la variable y el nombre del tipo de la variable a partir de la línea de declaración
Private Sub ObtenerVariableYtipo(ByVal VisualBasic As Boolean, ByVal Linea As String, _
ByRef var As String, ByRef tipo As String)
var = ""
tipo = ""
'Obtengo el nombre de la variable y su tipo
Dim mc = Regex.Matches(Linea.Trim, If(VisualBasic, REGEX_Declaracion_VB, REGEX_Declaracion_CSHARP), _
RegexOptions.IgnoreCase Or RegexOptions.Singleline)

If mc.Count = 0 Then
Throw New Exception("La línea actual no es la declaración de una variable")
End If

For Each m As Match In mc
var = m.Groups("var").ToString
tipo = m.Groups("tipo").ToString
Next
End Sub

'Devuelve el texto convertido a propiedad
Private Function DevolverPropiedad(ByVal VisualBasic As Boolean, _
ByRef var As String, ByRef tipo As String) As String
If VisualBasic Then
Return (String.Format( _
"Private _{1} As {2}{3}" & _
"Public Property {1}() As {2}{3}" & _
"{0}Get{3}" & _
"{0}{0}Return _{1}{3}" & _
"{0}End Get{3}" & _
"{0}Set(ByVal value As {2}){3}" & _
"{0}{0}_{1} = value{3}" & _
"{0}End Set{3}" & _
"End Property{3}", _
vbTab, var, tipo, vbCrLf))
Else
Return (String.Format( _
"{0}{0}public {1} {2} {{ get; set; }}", vbTab, tipo, var))
End If
End Function

End Module
A continuación guardar y cerrar la ventana del editor de macros.

Ahora ya existe el método thepirat.campo2prop que a partir de la línea actual del editor del Visual Studio, convierte la declaración de un campo a una declaración de una propiedad con el mismo nombre.



Sólo falta vincular un acceso directo para poder utilizar la macro con una combinación de teclas.

Para esto, ir al menú Tools, Customize y luego click en el botón Keyboard... Buscar el método campo2prop como se muestra a continuación:


Presionar la combinación de teclas deseada en la parte indicada y luego darle click en Assign

Listo! Ahora desde cualquier ventana del editor de Visual Studio, se puede hacer esto:

Me paro en la línea de la declaración de un campo:


Presiono mi combinación de teclas y obtengo:



Datos personales