技术开发 频道

使用Visual Studio 2005 IDE的宏,自动为c#变量生成属性

    【IT168技术文档】在编写c#代码过程中,我们经常需要做一些重复枯燥的工作。例如,编写DTO(数据访问对象),通常就是为一个类定义一系列的变量和属性。

    有一些第三方的IDE辅助工具,可以为我们生成一些代码,减少工作量。例如,Assist X就是一款很值得推荐的工具,使用其提供的Encapsulate Field功能,可以很方便地将一个类地编写封装为属性。

    我今天需要介绍的如何使用Visual Studio 2005 IDE中自带的宏实现类似的功能。

    打开Visual Studio 2005 IDE,选择“工具” > "宏" > “宏 IDE”,选择“添加模块”。例如,我是在MyMacros项目中新增了一个EditorHelper模块,代码如下:

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module EditorHelper
    
'为一个参数封装一般属性访问器
    Public Sub EncapsulateField()
        
Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        
Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel

        
'得到当前选定的内容
        Dim selectText As TextSelection = DTE.ActiveDocument.Selection
        
'获取到当前光标的位置
        Dim point As TextPoint = selectText.ActivePoint

        Try
            
Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, vsCMElement.vsCMElementVariable)

            
If (codeElement Is NothingThen
                Return
            
End If

            Debug.Assert(codeElement.Kind 
= vsCMElement.vsCMElementVariable)

            
Dim codeVar As CodeVariable = CType(codeElement, CodeVariable)
            
Dim fieldName As String = codeVar.Name
            
Dim codeClass As CodeClass = CType(codeVar.Parent, CodeClass)

            AddPropertyToClass(codeClass, fieldName, codeVar.Type)
        Catch ex 
As Exception
            
'吃掉异常,不做处理或者提示
        End Try

    
End Sub

    
Public Sub EncapsulateAllFields()
        
Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        
Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel

        Try
            
'得到当前选定的内容
            Dim selectText As TextSelection = DTE.ActiveDocument.Selection
            
'获取到当前光标的位置
            Dim point As TextPoint = selectText.ActivePoint

            
Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, vsCMElement.vsCMElementClass)
            
Dim codeClass As CodeClass = CType(codeElement, CodeClass)

            
Dim i As Integer
            
For i = 1 To codeClass.Members.Count
                
'如果属性已经定义,会抛出异常
                '在这里处理异常,即使新增的属性已经定义,也可以继续处理下面的代码
                Try
                    
Dim element As CodeElement = codeClass.Members.Item(i)
                    
If (element.Kind = vsCMElement.vsCMElementVariable) Then
                        
Dim codeVariable As CodeVariable = CType(element, CodeVariable)
                        
If (Not codeVariable.IsShared) Then     '静态变量不需要增加属性
                            AddPropertyToClass(codeClass, codeVariable.Name, codeVariable.Type)
                        
End If
                    
End If
                Catch ex 
As Exception
                    
'吃掉异常
                End Try
            
Next
        Catch ex 
As Exception
            
'可能并没有选择有效的类定义,这时会抛出异常,忽略
        End Try
    
End Sub

    
'根据成员的名称的类型,在类对象中插入属性
    Private Sub AddPropertyToClass(ByVal codeClass As CodeClass, ByVal fieldName As String, ByVal fieldType As Object)
        
'生成属性的名称,规则是首先字母大写。如果变量的开头为“_”,移除
        Dim propertyName As String = fieldName
        
If (propertyName.StartsWith("_")) Then
            propertyName 
= propertyName.TrimStart("_"c)
        
End If
        propertyName 
= propertyName.Substring(01).ToUpper() & propertyName.Substring(1)

        
'创建属性对象
        '-1表示代码插入到类的最下方
        'vsCMAccess.vsCMAccessPublic表示为public
        Dim codeProperty As CodeProperty = codeClass.AddProperty(propertyName, propertyName, fieldType, -1, vsCMAccess.vsCMAccessPublic)
        
'Getter
        Dim getter As CodeFunction = codeProperty.Getter
        
Dim getterPoint As TextPoint = getter.GetStartPoint(vsCMPart.vsCMPartBody)
        
Dim getterEditPoint As EditPoint = getterPoint.CreateEditPoint()
        getterEditPoint.Delete(getter.GetEndPoint(vsCMPart.vsCMPartBody))
        getterEditPoint.Insert(vbCrLf)      
'插入回车符
        getterEditPoint.LineUp()
        getterEditPoint.Indent(, 
4)         '缩进4个位置
        getterEditPoint.Insert("return " & fieldName & ";")
        
'Setter
        Dim setter As CodeFunction = codeProperty.Setter
        
Dim setterPoint As TextPoint = setter.GetStartPoint(vsCMPart.vsCMPartBody)
        
Dim setterEditPoint As EditPoint = setterPoint.CreateEditPoint()
        setterEditPoint.Insert(vbCrLf)     
'插入回车符
        setterEditPoint.LineUp()
        setterEditPoint.Indent(, 
4)         '缩进4个位置
        setterEditPoint.Insert(fieldName & " = value;")
    
End Sub
End Module

0
相关文章