c#变量生成属性.docx
《c#变量生成属性.docx》由会员分享,可在线阅读,更多相关《c#变量生成属性.docx(9页珍藏版)》请在冰豆网上搜索。
c#变量生成属性
使用VisualStudio2005IDE的宏,自动为c#变量生成属性
在编写c#代码过程中,我们经常需要做一些重复枯燥的工作。
例如,编写DTO(数据访问对象),通常就是为一个类定义一系列的变量和属性。
有一些第三方的IDE辅助工具,可以为我们生成一些代码,减少工作量。
例如,AssistX就是一款很值得推荐的工具,使用其提供的EncapsulateField功能,可以很方便地将一个类地编写封装为属性。
我今天需要介绍的如何使用VisualStudio2005IDE中自带的宏实现类似的功能。
打开VisualStudio2005IDE,选择“工具”>"宏">“宏IDE”,选择“添加模块”。
例如,我是在MyMacros项目中新增了一个EditorHelper模块,代码如下:
ImportsSystem
ImportsEnvDTE
ImportsEnvDTE80
ImportsSystem.Diagnostics
PublicModuleEditorHelper
'为一个参数封装一般属性访问器
PublicSubEncapsulateField()
DimprojectItemAsProjectItem=DTE.ActiveDocument.ProjectItem
DimfileCodeModelAsFileCodeModel=projectItem.FileCodeModel
'得到当前选定的内容
DimselectTextAsTextSelection=DTE.ActiveDocument.Selection
'获取到当前光标的位置
DimpointAsTextPoint=selectText.ActivePoint
Try
DimcodeElementAsCodeElement=fileCodeModel.CodeElementFromPoint(point,vsCMElement.vsCMElementVariable)
If(codeElementIsNothing)Then
Return
EndIf
Debug.Assert(codeElement.Kind=vsCMElement.vsCMElementVariable)
DimcodeVarAsCodeVariable=CType(codeElement,CodeVariable)
DimfieldNameAsString=codeVar.Name
DimcodeClassAsCodeClass=CType(codeVar.Parent,CodeClass)
AddPropertyToClass(codeClass,fieldName,codeVar.Type)
CatchexAsException
'吃掉异常,不做处理或者提示
EndTry
EndSub
PublicSubEncapsulateAllFields()
DimprojectItemAsProjectItem=DTE.ActiveDocument.ProjectItem
DimfileCodeModelAsFileCodeModel=projectItem.FileCodeModel
Try
'得到当前选定的内容
DimselectTextAsTextSelection=DTE.ActiveDocument.Selection
'获取到当前光标的位置
DimpointAsTextPoint=selectText.ActivePoint
DimcodeElementAsCodeElement=fileCodeModel.CodeElementFromPoint(point,vsCMElement.vsCMElementClass)
DimcodeClassAsCodeClass=CType(codeElement,CodeClass)
DimiAsInteger
Fori=1TocodeClass.Members.Count
'如果属性已经定义,会抛出异常
'在这里处理异常,即使新增的属性已经定义,也可以继续处理下面的代码
Try
DimelementAsCodeElement=codeClass.Members.Item(i)
If(element.Kind=vsCMElement.vsCMElementVariable)Then
DimcodeVariableAsCodeVariable=CType(element,CodeVariable)
If(NotcodeVariable.IsShared)Then'静态变量不需要增加属性
AddPropertyToClass(codeClass,codeVariable.Name,codeVariable.Type)
EndIf
EndIf
CatchexAsException
'吃掉异常
EndTry
Next
CatchexAsException
'可能并没有选择有效的类定义,这时会抛出异常,忽略
EndTry
EndSub
'根据成员的名称的类型,在类对象中插入属性
PrivateSubAddPropertyToClass(ByValcodeClassAsCodeClass,ByValfieldNameAsString,ByValfieldTypeAsObject)
'生成属性的名称,规则是首先字母大写。
如果变量的开头为“_”,移除
DimpropertyNameAsString=fieldName
If(propertyName.StartsWith("_"))Then
propertyName=propertyName.TrimStart("_"c)
EndIf
propertyName=propertyName.Substring(0,1).ToUpper()&propertyName.Substring
(1)
'创建属性对象
'-1表示代码插入到类的最下方
'vsCMAccess.vsCMAccessPublic表示为public
DimcodePropertyAsCodeProperty=codeClass.AddProperty(propertyName,propertyName,fieldType,-1,vsCMAccess.vsCMAccessPublic)
'Getter
DimgetterAsCodeFunction=codeProperty.Getter
DimgetterPointAsTextPoint=getter.GetStartPoint(vsCMPart.vsCMPartBody)
DimgetterEditPointAsEditPoint=getterPoint.CreateEditPoint()
getterEditPoint.Delete(getter.GetEndPoint(vsCMPart.vsCMPartBody))
getterEditPoint.Insert(vbCrLf)'插入回车符
getterEditPoint.LineUp()
getterEditPoint.Indent(,4)'缩进4个位置
getterEditPoint.Insert("return"&fieldName&";")
'Setter
DimsetterAsCodeFunction=codeProperty.Setter
DimsetterPointAsTextPoint=setter.GetStartPoint(vsCMPart.vsCMPartBody)
DimsetterEditPointAsEditPoint=setterPoint.CreateEditPoint()
setterEditPoint.Insert(vbCrLf)'插入回车符
setterEditPoint.LineUp()
setterEditPoint.Indent(,4)'缩进4个位置
setterEditPoint.Insert(fieldName&"=value;")
EndSub
EndModule
我定义了两个Public方法:
EncapsulateField和EncapsulateAllFields,分别用于为类的一个变量封装属性,或者为类中所有的变量(非静态)封装属性。
使用上面的宏的方法很简单,选择“工具”>“宏”>“宏资源管理器”就可以看到我们已经创建的宏方法,如下图所示:
假如你已经编写了这样一段代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceDemo
{
publicclassPerson
{
privateint_id;
privatestring_name;
privateDateTime_birthDay;
}
}
将光标移到“_name”变量上,然后双击“EncapsulateField”宏,就运行了该宏。
运行后,你可以得到这样的代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceDemo
{
publicclassPerson
{
privateint_id;
privatestring_name;
privateDateTime_birthDay;
publicstringName
{
get
{
return_name;
}
set
{
_name=value;
}
}
}
}
可以看到“EncapsulateField”宏已经为privatestring_name;创建了相应的属性。
EncapsulateAllFields宏只需要将光标放在Person类的代码区域中,就可以正常执行。
例如针对上面的代码,EncapsulateAllFields后可以为Person类中的每一个变量都生成相应的属性。
(注:
上面的代码中Name属性已经有定义,所有试图再添加Name属性时会抛出异常,在EncapsulateAllFields宏定义中,已经将该异常吃掉,所以,可以正确地为所有变量生成属性)。
运行后的代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceDemo
{
publicclassPerson
{
privateint_id;
privatestring_name;
privateDateTime_birth