通过PropertyManager Add-In管理代码中的属性

简介:

前言

可扩展性开发(七)中,我介绍了如何对VS中的编辑器进行操作。在CodeTemplate例子中可以看到,大部分的工作量不是在编辑器的操作上,而是在于相关功能的逻辑处理上。本文将介绍另一个与编辑器相关的例子PropertyManager。

问题分析

PropertyManager用来管理代码中的属性。我们在C# 3.0之前编写代码时,与属性相关的主要操作是将字段封装为属性,VS 2005中的Refactor->Encapsulate Field菜单(快捷键Ctrl+R, E)可以简化这个操作。它每次封装一个字段,并将生成的属性放在字段所在行的下一行,但是大部分人的编码习惯是将字段放在一起,将属性们放在一起,所以首先PropertyManager要做到这一点。

C#3.0引入了自动属性的特性,使得我们在处理简单属性的时候更为简单。但是我们有时候还是需要使用传统风格的属性声明方式,PropertyManager还要能在这两种声明方式之间进行转化。(这个需求来自于园子里的Clingingboy

下面就来看看如何在Add-In中实现这些功能。

实现PropertyManager

1)添加命令

按上面的分析,这里需要三个命令,界面看起来像这样:

property-manager-menu

Batch Property为选中的多个字段生成属性代码。这里将原有的传统的声明方式称为Normal-Property,将自动属性称为Auto-Property,后面的两个命令即是在这两种方式间进行转换。

使用下面的代码添加命令:

 

复制代码
C# Code - 添加ProjectManager命令
CommandBar codeWinCommandBar = helper.GetCommandBarByName("Code Window");

int pmPopupIndex = codeWinCommandBar.Controls.Count + 1;
CommandBarPopup pmPopup 
= codeWinCommandBar.Controls.Add(
    MsoControlType.msoControlPopup, Type.Missing, Type.Missing,
    pmPopupIndex, 
trueas CommandBarPopup;
pmPopup.Caption 
= "PropertyManager";

CommandBarButton batchPropertyCmd 
= helper.AddButtonToPopup(pmPopup, pmPopup.Controls.Count + 1,
    
"Batch Property""Encapsulate these fields");
batchPropertyCmdEvent 
= _applicationObject.Events.get_CommandBarEvents(batchPropertyCmd) as CommandBarEvents;
batchPropertyCmdEvent.Click 
+= new _dispCommandBarControlEvents_ClickEventHandler(BatchPropertyCmdEvent_Click);

CommandBarButton convertToAutoPropCmd 
= helper.AddButtonToPopup(pmPopup, pmPopup.Controls.Count + 1,
    
"Convert to Auto-Property""Convert to Auto-Property(C# 3.0 style)");
convertToAutoPropCmdEvent 
= _applicationObject.Events.get_CommandBarEvents(convertToAutoPropCmd) as CommandBarEvents;
convertToAutoPropCmdEvent.Click 
+= new _dispCommandBarControlEvents_ClickEventHandler(ConvertToAutoPropCmdEvent_Click);

CommandBarButton convertToNormalPropCmd 
= helper.AddButtonToPopup(pmPopup, pmPopup.Controls.Count + 1,
    
"Convert to Normal-Property""Convert to Normal-Property(C# 2.0 style)");
convertToNormalPropCmdEvent 
= _applicationObject.Events.get_CommandBarEvents(convertToNormalPropCmd) as CommandBarEvents;
convertToNormalPropCmdEvent.Click 
+= new _dispCommandBarControlEvents_ClickEventHandler(ConvertToNormalPropCmdEvent_Click);
复制代码


2)命令的实现

为简化问题,这里约定字段、自动属性和常规属性的声明格式为:

复制代码
C# Code - 字段和属性约定格式
private int id;
string name;
private DateTime birth;

private int Id { getset; }
public string Name { private getset; }
public DateTime Birth { getprivate set; }

public int Id
{
    
get { return id; }
    
set { id = value; }
}
public string Name
{
    
get { return name; }
    
set { name = value; }
}
public DateTime Birth
{
    
get { return birth; }
    
set { birth = value; }
}
复制代码


字段采用camelCase风格命名,属性采用PascalCase风格命名。

在实现Batch Property时,可以采用正则表达式找出选中行中的多个字段,为它们一一生成属性,最后将属性代码放入剪贴板:

C# Code - 实现BatchProperty命令


GetSelectedLines方法是获取当前文档中选中的代码行:

C# Code - 获取选中的文本行


字段可能为readonly的,此时将只生成getter代码。这样在生成属性时考虑的主要因素为:字段类型、字段名称、是否只读。这样

C# Code
private int id;
string name;
private readonly DateTime birth;


会生成如下的代码(会拷贝到剪贴板中):

复制代码
C# Code
public int Id
{
    
get { return id; }
    
set { id = value; }
}
public string Name
{
    
get { return name; }
    
set { name = value; }
}
public DateTime Birth
{
    
get { return birth; }
}
复制代码


在实现Convert to Auto-Property时,思路与上面相同,也是将查找到的各个常规属性转换为自动属性:

C# Code - 实现Convert to Auto-Property命令


对于代码

复制代码
public   int  Id
{
    
get  {  return  id; }
    
set  { id  =  value; }
}
public   string  Name
{
    
set  { name  =  value; }
}
public  DateTime Birth
{
    
get  {  return  birth; }
}
复制代码


生成的结果为:

public   int  Id {  get set ; }
public   string  Name {  private   get set ; }
public  DateTime Birth {  get private   set ; }


最后是Convert to Normal-Property

复制代码
C# Code - 实现Convert to Normal-Property命令
private void ConvertToNormalPropCmdEvent_Click(object CommandBarControl, ref bool Handled, ref bool CancelDefault)
{
    
string selectedLines = helper.GetSelectedLines();
    Regex propRegex 
= new Regex(
        
"((?<modifier>\\w+)?\\s+)?(?<type>\\w+)\\s+(?<name>\\w+)\\s*{(.|\\n)*?get;(.|\\n)*?set;\\s*}",
        RegexOptions.IgnoreCase 
| RegexOptions.Multiline);
    MatchCollection autoProperties 
= propRegex.Matches(selectedLines);

    StringBuilder normalProps 
= new StringBuilder();
    
foreach (Match prop in autoProperties)
    {
        
string modifier = prop.Groups["modifier"].Value;
        
string type = prop.Groups["type"].Value;
        
string name = prop.Groups["name"].Value;

        
string propText = prop.Value;
        
bool writeOnly = Regex.IsMatch(propText, "private\\s+get;");
        
bool readOnly = Regex.IsMatch(propText, "private\\s+set;");
        
if (writeOnly && readOnly) { break; }

        normalProps.AppendLine(GenerateNormalProperty(modifier, type, name, readOnly, writeOnly));
    }

    Clipboard.SetText(normalProps.ToString());
}
复制代码


至此这三个命令就全部实现了,它们都是将结果放在剪切板中,因为我感觉很难确定出一个合适的位置。

可以从这里下载代码,也可以在这里下载可运行的Add-In(解压缩后将文件放在[My Documents Path]\Visual Studio 2008\Addins下)。

希望这个功能能让您对编辑器的扩展有更多的了解。



本文转自一个程序员的自省博客园博客,原文链接:http://www.cnblogs.com/anderslly/archive/2009/04/01/vs-addin-property-manager.html,如需转载请自行联系原作者。

目录
相关文章
|
Oracle 安全 关系型数据库
搭建 OpenLDAP 自助修改密码系统
让修改open ldap密码变得简单
1509 0
搭建 OpenLDAP 自助修改密码系统
|
网络协议 数据可视化 Ubuntu
可视化web管理的内网穿透神器NPS
可视化web管理的内网穿透神器NPS
可视化web管理的内网穿透神器NPS
|
数据可视化 IDE 安全
云巧-让开发更简单,更高效,更方便
近年来,快速迭代的新需求将引导企业改变其开发方式,进而转向使用支持快速、安全和高效的技术架构,组装式应用便成为了企业重要的战略技术趋势。组装式应用引入模块化的理念,使得各企业可以更敏捷、更有效地复用能力模块,提高商业的韧性和效率。云巧平台应运而生,能极大的改善开发环境,节省开发工作量,让开发更简单,更高效,更方便。
2228 0
|
传感器 物联网 开发工具
基于华为物联网云平台设计的智能家居控制系统(STM32+ESP8266)
现在可以接入的物联网云平台非常多,阿里云物联网云平台、OneNet中国移动物联网云平台,还有机智云、涂鸦智能、百度云平台、华为云平台等等。
1259 1
|
数据采集 SQL 存储
DataWorks数据质量介绍及实践 | 《一站式大数据开发治理DataWorks使用宝典》
数据质量问题虽然从数据工程师的角度来看是个简单问题,但是从业务的角度来看是个很严重的问题。所以数据质量是数据开发和治理全生命周期中,非常重要的一个环节。在DataWorks产品版图里,数据质量也是非常重要的模块之一。
4800 0
DataWorks数据质量介绍及实践 | 《一站式大数据开发治理DataWorks使用宝典》
|
机器学习/深度学习 搜索推荐 算法
“会员营销API:自动化积分与优惠券,增强用户粘性”
会员营销API集积分管理、优惠券发放、用户行为追踪等功能于一体,助力企业自动化运营,降低成本并提升体验。其核心功能涵盖自动化积分系统、优惠券策略优化、数据整合与用户画像分析、跨平台体验管理,以及安全风控机制。通过实时同步积分、动态调整优惠力度和多终端数据整合,增强用户参与感与忠诚度。同时,提供效果评估工具和A/B测试接口,结合机器学习算法优化营销策略,实现精准化、高效化的会员管理与留存提升。
96 0
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
1463 1
|
编译器
Qt没有被正确安装,请运行make install -- 问题的解决办法
Qt没有被正确安装,请运行make install -- 问题的解决办法
1503 0
|
存储 设计模式 前端开发
浅谈领域驱动设计实践——董炎焱
近年来领域驱动设计(Domain Drive Design)大火。那么我们为什么要学习领域驱动设计,它适合用于哪些场景?怎么去用?在用的过程中,又有哪些需要注意的地方呢?
浅谈领域驱动设计实践——董炎焱