上篇:设计

一、引子

自2008年起开发SSMS插件SqlSharp(er)的过程中,有一天发现多数代码都大同小异,就像这样。

 Commands2 commands = (Commands2)_applicationObject.Commands;
string toolsMenuName = "Tools"; //Place the command on the tools menu.
//Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"]; //Find the Tools command bar on the MenuBar command bar:
CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl; //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
// just make sure you also update the QueryStatus/Exec method to include the new command names.
try
{
//Add a command to the Commands collection:
// add + (int)vsCommandStatus.vsCommandStatusEnabled if we want the default state to be enabled
Command command = commands.AddNamedCommand2(_addInInstance, "FormatSQL", "Format SQL", "Format SQL", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); //Add a control for the command to the tools menu:
if ((command != null) && (toolsPopup != null))
{
command.AddControl(toolsPopup.CommandBar, 1);
}
}
catch (System.ArgumentException)
{
//If we are here, then the exception is probably because a command with that name
// already exists. If so there is no need to recreate the command and we can
// safely ignore the exception.
}

于是萌生出开发一个框架的想法。

于是有了一个叫SsmsSharp的框架,后正式命名为SqlSharp发布到了CodePlex上。

与此同时,将操纵EnvDTE的代码与SSMS Objects的代码分离,操纵EnvDTE的代码就形成了本篇要说的VsSharp。

后来,当我正式使用VsSharp开发VS扩展时,又引出一些新问题如源代码签出、一个VS搭载多个扩展,解决这些问题后,VsSharp开始成熟起来。

二、设计思路

1、目标

应用Command模式,定义每个控件的行为。将一个个控件的属性与行为集合在一个配置文件中,在VS启动时自动加载控件,点击控件时通过反射触发相应的命令。

2、流程

User:终端用户(也就是各位码农)

Host:VS实例,提供全局的EnvDTE对象访问器,注册Plugin,响应IDE的各种事件(如文档打开关闭等)

Plugin:基于VsSharp开发的插件(此处为避免与EnvDTE.AddIn重名,命名为Plugin)

由此引出VsSharp的职责

  1. 负责配置的加载
  2. 向VS注册控件
  3. 响应用户的点击及其他事件

三、概要设计

1、对象设计

1.1 基于上述职责定义,抽象出如下对象:

  • CommandConfig:负责命令与控件的配置描述
  • CommandManager:负责配置的加载,和与VS的交互
  • CommandBarAccessor:与VS直接交互的对象,实现ICommandBarAccessor接口,主要是为了隔离VS版本的差异
  • Host:宿主,单例,表示当前操作的VS实例;CommandAccessor通过它与EnvDTE交互
  • PlugIn:主要属性为CommandConfig和Connect入口的Assembly

CommandBarAccessor的行为:

 public interface ICommandBarAccessor
{
void AddControl(CommandControl control);
void ResetControl(CommandControl control);
void EnableControls(IEnumerable<string> ids ,bool enabled);
void Delete();
}
  • AddContro:添加一个控件
  • ResetControl:重置控件,比如某控件的子菜单可以依赖于特定的配置或数据源,当配置或数据源发生变化时,需要重新加载控件
  • EnableControl:启用(禁用)控件,比如某些控件是用于操作文档的,当有文档打开时才启用
  • Delete:删除控件,当VS退出时执行Disconnect方法时触发

1.2 命令接口

 public interface ICommand
{
void Execute(object arg = null);
}

命令类型:

 public enum CommandActionType
{
Menu,
Program,
Window,
Dialog
}
  • Menu:缺省类型,无任何行为
  • Program:执行一段程序
  • Window:打开一个窗体
  • Dialog:打开一个模态窗体

1.3 命令控件描述

主要有两种控件类型:

  • CommandMenu:包括主菜单栏的自定义菜单、上下文菜单,其下级可以有子菜单
  • CommandButton:主要是插入ToolStrip的ToolStripButton,其下级也可以有子菜单

抽象类CommandControl:CommandMenu和CommandButton的父类,描述控件的ID、文本、图标、命令类型、位置、所属父控件等属性。

以下代码段为CommandControl的全部属性。

其中,

ClassName为供反射用的动作类型名称,当CommandActionType为Program时,要求该类型实现了ICommand接口。

 

CommandMenu继承CommandControl,特有子菜单相关属性。

其中SubMenus属性可在编程时操纵,SubGeneratorType为配置文件中定义的供反射用的子菜单生成器类型,用于启动时根据特定数据源自动生成。

 

2、类图

调用关系 :

  • Connect对象启动时加载CommandConfig,生成一个Plugin对象传给CommandManager,并向Host.Instance注册;CommandManager加载CommandConfig描述的所有控件
  • Connect.OnConnection方法调用CommandManager.Load方法
  • Connect.Exec方法调用CommandManager.Execute方法
  • Connect.OnDisconnection方法调用CommandManager.Disconnect方法

四、源代码

http://vssharp.codeplex.com/

---------------------------------------------------

下篇将以一个实例来讲解框架的使用,敬请期待。

作者:CnSharp.com
本文版权归CnSharp.com和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
 

VS扩展开发框架的更多相关文章

  1. VsSharp:一个VS扩展开发框架(上)

    上篇:设计 一.引子 自2008年起开发SSMS插件SqlSharp(er)的过程中,有一天发现多数代码都大同小异,就像这样. Commands2 commands = (Commands2)_app ...

  2. Linux 搭建php扩展开发框架

    1.安装phpize(如果是使用php源码编译就免了,本身就有) 2.打开php源码,ext中有ext_skel工具,使用它可以方便 ./ext_skel --extname = myext 生成扩展 ...

  3. VS2012编译php扩展

    注意:用VS2015来做会比较好! 开发前准备工作:cygwinvisual studio 2012php编译后的程序      使用的是 xampp集成安装包,所以编译后的程序路径为D:\xampp ...

  4. 几种流行Webservice框架性能对比(转载)

    1摘要 开发webservice应用程序中离不开框架的支持,当open-open网站列举的就有很多种,这对于开发者如何选择带来一定的疑惑.性能Webservice的关键要素,不同的框架性能上存在较大差 ...

  5. DDD开发框架ABP之本地化资源的数据库存储扩展

    在上一篇<DDD开发框架ABP之本地化/多语言支持>中,我们知道,ABP开发框架中本地化资源存储可以采用XML文件,RESX资源文件,也提供了其他自定义的存储方式的扩展接口.ABP框架默认 ...

  6. 在开发框架中扩展微软企业库,支持使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库

    在前面随笔<在代码生成工具Database2Sharp中使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库,实现免安装Oracle客户端,兼容3 ...

  7. vue+.netcore可支持业务代码扩展的开发框架 VOL.Vue 2.0版本发布

    框架介绍 这是一个基于vue.element-ui.iview..netcore3.1 可支持前端.后台动态扩展业务代码快速开发框架. 框架内置定制开发的代码生成器,生成的代码不需要复制也不需要更改, ...

  8. [原创][开源]SunnyUI.Net, C# .Net WinForm开源控件库、工具类库、扩展类库、多页面开发框架

    SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...

  9. SpringCloud微服务实战——搭建企业级开发框架(四十一):扩展JustAuth+SpringSecurity+Vue实现多租户系统微信扫码、钉钉扫码等第三方登录

      前面我们详细介绍了SSO.OAuth2的定义和实现原理,也举例说明了如何在微服务框架中使用spring-security-oauth2实现单点登录授权服务器和单点登录客户端.目前很多平台都提供了单 ...

随机推荐

  1. 【原创】leetCodeOj --- Excel Sheet Column Title 解题报告

    题目地址: https://oj.leetcode.com/problems/excel-sheet-column-title/ 题目内容: Given a positive integer, ret ...

  2. 微渠道发展 BAE交通运输平台和java呼声,微信mysql数据库开发实例 --图文开发教程

    持续更新 BAE java开展mysql数据库 图文教程 BAE java语言发展mysql源码下载: 目前微信的发展.BAE开展.java开展.mysql教程开发非常,的介绍基于BAE平台.java ...

  3. 神马是AB測试?

    手机响起了短信提示音,桂芬拿起手机,滑动解锁,看到是来福的短信,心里不禁一阵小鹿乱撞.     "喜欢看<冰封重生之门>吗?"     如此充满暗示意味的短信让桂芬激动 ...

  4. js在以div添加滚动条

    给予div另外,当我们必须定义高度和宽度的滚动条,使滚动条是有效,增加样式:overflow:auto; 版权声明:本文博主原创文章.博客,未经同意不得转载.

  5. enumerateObjectsUsingBlock、enumerateObjectsWithOptions、enumerateObjectsAtIndexes、makeObjectsPerfor使用

    OC至 NSArray它提供了一个方便的遍历block,以下具体说明 第一.enumerateObjectsUsingBlock NSArray *array=@[@"aa",@& ...

  6. 最佳新秀SSH十六Struts2它是如何工作的内部

    前面说完了Spring.Hibernate,非常自然今天轮到struts了.struts的核心原理就是通过拦截器来处理client的请求,经过拦截器一系列的处理后,再交给Action.以下先看看str ...

  7. POJ - 3249 Test for Job (DAG+topsort)

    Description Mr.Dog was fired by his company. In order to support his family, he must find a new job ...

  8. hdu3844 Mining Your Own Business,无向双连接组件

    点击打开链接 无向图的双连通分量 #include<cstdio> #include<stack> #include<vector> #include<map ...

  9. Hibernate学习笔记(1)Hibernate构造

    一 准备工作 首先,我们将创建一个简单的基于控制台(console-based)Hibernate应用. 我们所做的第一件事就是创建我们的开发文件夹.并把所有需要用到的Java件放进去.解压缩从Hib ...

  10. [LeetCode283]Move Zeros将一个数组中为0的元素移至数组末尾

    题目: Given an array nums, write a function to move all 0's to the end of it while maintaining the rel ...