VSX-4 VSXTra
要介绍VSXTra项目不是一个简单的事情。 而且要在上面进行扩展,删减就更不容易。 源码分析的资料几乎没有,可怜的几个示例项目,相较而言,英文已经不是阻碍我前进的步伐了。 本篇只是简单的分析,对于已经使用到的几个接口或类型进行说明,不可能完整的,从全局去介绍VSXTra项目,建议读者还是去啃LearnVSXNow!系列,其中有不少的篇幅在介绍这个项目。
PackageBase
不管是CommandHandlerBase还是PowerCommands,都是简单的封装而已,但是VSXTra里的PackageBase并没有继承于Package,实际上它只是实现了几个接口。
这里首先要说的是IVsPackage这个接口。 VS2010使用MEF做扩展,实现了IVsPackage接口的会首先调用其SetSite方法,其实从PackageBase的InternalInitialize方法就可以看出两个调用的地方,另一个是IVsShellPropertyEvents的OnShellPropertyChange方法。 而并不是VS已启动就会加载VSPackage的,而是当你第一次使用该VSPackage的功能时才会加载,要实现自动加载VSPackage,你需要在你的VSPackage上标注自动运行才行,[ProvideAutoLoad(UIContextGuids.SolutionExists)]
大概的意思就是,当解决方案存在的时候,该VSPackage自动加载。 这里没有使用VSXTra里所说的Typed GUID,而是直接使用UIContextGuids的常量定义,其实我现在仍然不知道这样写有什么好处。 之后在用户启动VS,打开某个解决方案时,IVsPackage的SetSite方法才会触发。 而IVsShellPropertyEvents的OnShellPropertyChange方法与IVsPackage的SetSite方法有所区别,SetSite对于每个VSPackage只会加载一次,而OnShellPropertyChange是当用户切换VSPackage时会触发,且里面那句经典的判断,能隔绝大多数情况的触发:
if ((int)__VSSPROPID.VSSPROPID_Zombie == propid)
{
if ((bool)propValue == false)
{
}
}
我已经不记得我如何得出以上结论,当然你肯定能想到,那都是很艰难很艰难的。
Command
我实在不想过多介绍PackageBase,这里借道Command缓冲缓冲。 当初如何实现一个Command以及PowerCommands对命令的简单封装我这里就不再啰嗦了,看看VSXTra里对Command的处理。
[CommandExecMethod]
[CommandId(GuidList.guidVSXtraMenuCommandCmdSetString,
CmdIDs.cmdidVSXtraMenuCommand)]
private void MyMenuCommand()
{
VsMessageBox.Show("Inside VSXtra Menu Command");
}
这是VSXTra里一个经典的实现方式,对于界面关系极少的VSPackage很有用,不需要其他任何代码,只在Package里加一个方法,标注几个Attribute即可,不可谓不方便。 可惜我的项目中,多个VSPackage共同组合,Command每个VSPackage中一大堆,即使使用分部类也过于麻烦。
[Guid(GuidList.guidCompileCmdSetString)]
public partial class BuildTradeGroup : CommandGroup<CompilePackage>
{
[CommandId(PkgCmdIDList.cmdidBuildTrade)]
public sealed class BuildTradeCommand : MenuCommandHandler
{
protected override void OnExecute(OleMenuCommand command)
{
}
}
}
VSXTra的示例项目中有这么一个例子,介绍了这种PowerCommands的分离方式。 可以看出,不同之处就是原本的CommandId是两个参数,需要传CmdSet的Guid,还要传Cmd的Id,而这里使用了CommandGroup去将其分类,这样以来确实看起来逻辑清楚,怎奈我还是想要每个命令一个文件的形式去做,所以这里使用了分部类,但是Guid只能在一个上面标注让我很是不爽,且每次新建命令,都忘了修改CommandId让人很是抓狂。 我在UnitTest专门对此进行检测。
再回首PackageBase
其实在VSXTra中,实现Command和PowerCommands中没有多大区别,关键代码就在PackageBase中。 在上面介绍的SetSite和OnShellPropertyChange方法中触发了InternalInitialize方法,其中又触发了BindCommandHandlers方法,而从传过来的程序集中就能看出其实现原理。 其实平淡无奇,只是遍历程序集中所有类,然后找出需要的类,通过Activator.CreateInstance方法实例化,进行相应的操作。 所以这里我扩展了对SolutionListeners和Configuration的初始化。 当然,PackageBase不只是对Command做了简化,比如说IVsPersistSolutionOpts接口就是对OptionPage进行的操作,而IVsToolWindowFactory接口就是对ToolWindow进行的操作。
Package中比较重要的一个方法GetService,其实是对IServiceProvider的GetService实现,期间嵌套了对IOleServiceProvider(Microsoft.VisualStudio.OLE.Interop.IServiceProvider)的QueryService实现。 读GetService很具挑战力,太过费心费力,这里不想继续了。
IServiceProvider接口是VSX开发中一个比较重要的接口,所以在PackageBase中对其做了全局实例,包括弹出框、DTE对象等一系列都需要使用IServiceProvider去获取。
PackageBase作为对Package的替代者,很多人只意识到继承关系,而其他诸如静态方法的实现却仍然使用Package提供的。 几乎所有Package实现的东西,PackageBase都能实现,且实现的更为方便快捷。 有一个简单而明显的例子,就是GetGlobalService方法,PackageBase对其做了三个重载,这也是在VSXTra项目中大量出现的一种重载方式,规范了很多调用方法。当然,不排除对于新接触的人各种疑惑。
前面简单的介绍了VSXTra开源框架,至于深究,还是算了,我只是祈祷我做的修改和扩展不会出错就好,而ProjectSystem项目更让我畏惧三分。 使用VSXTra确实能简化开发,而且更重要的是,在参考资料如此少的情况下,这么一个框架给我提供的就不只是简化开发而已,更多的是对VSX开发的进一步认识。
后续文章中可能会继续介绍VSXTra框架,分析其中一些具体的实现方式,以及我对VSXTra框架做的一些扩展。
VSX-4 VSXTra的更多相关文章
- 【Visual Studio】在VS2012中使用VSXtra
最近工作中需要把之前为VS 2010写的扩展迁移到VS 2012上.在将工程版本改为VS2012之后,代码没有修改,直接编译通过,也可以安装到VS2012上. 不过,在实际使用的时候,却报错,提示“T ...
- VSX规划Package文件
VSX是VS扩展,可以针对不同项目编写插件,虽然接触VSX的时间并不多,但是当了解VSX后深刻感受到VSX的魅力. VSX的材料比较少,配置文件也很繁琐,当初我也走了不少弯路. 这篇文章将帮助您更好的 ...
- VSX(翻译)Moving Code Blocks Among Code Regions using VS 2010 Extensions
Moving Code Blocks Among Code Regions using VS 2010 Extensions (翻译)使用VS 2010 扩展性将代码块移至Region区域中 Down ...
- 【JZOJ2156】【2017.7.10普及】复仇者vsX战警之训练
题目 月球上反凤凰装甲在凤凰之力附身霍普之前,将凤凰之力打成五份,分别附身在X战警五大战力上面辐射眼.白皇后.钢力士.秘客和纳摩上(好尴尬,汗). 在凤凰五使徒的至高的力量的威胁下,复仇者被迫逃到昆仑 ...
- C# base 64图片编码解码
使用WinForm实现了图片base64编码解码的 效果图: 示例base 64编码字符串: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKD ...
- java web学习总结(二十七) -------------------JSP标签介绍
一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...
- Oracle学习笔记十 使用PL/SQL
PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...
- PHP代码 如何网页获取用户的openid
public function getOpenid($appid, $appsecret) { $SERVER_NAME = $_SERVER['SERVER_NAME']; $REQUEST_URI ...
- PHP中的header()函数作用
PHP 中 header()函数的作用是给客户端发送头信息. 什么是头信息?这里只作简单解释,详细的自己看http协议.在 HTTP协议中,服务器端的回答(response)内容包括两部分:头信息(h ...
随机推荐
- 掌握这些技能玩转iOS
近一年来,苹果iOS/OS X频繁被爆出重大安全漏洞,攻击者可以通过漏洞窃取多达上千个应用的密码.这些漏洞一旦被黑客掌握.利用,后果不堪设想. 好在这些漏洞的发现者还是有节操的,他们都将这些漏洞汇报给 ...
- Linux 使用第三方邮箱发邮件的设置
mail命令在Ubuntu下是需要安装的,使用下条命令进行安装: sudo apt-get install heirloom-mailx 在CentOS 下安装则是: yum install mail ...
- Windows 静态IP脚本
@echo off echo 快速设置IP地址和DNS为“静态” set 连接名称=以太网 set ip地址=192.168.1.80 set 子网掩码=255.255.255.0 set 网关地址= ...
- 非常全面的PHP header函数设置HTTP头的示例
突然看到这个,觉得很好,就拿过来了,如下: //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Conten ...
- bzoj2568 比特集合
Description 比特集合是一种抽象数据类型(Abstract Data Type) ,其包含一个集合S,并支持如下几种操作: INS M : 将元素 M 插入到集合S中: DEL M : 将集 ...
- 2017.10.14 Java的流程控制语句switch&&随机点名器
今日内容介绍 1.流程控制语句switch 2.数组 3.随机点名器案例 ###01switch语句解构 * A:switch语句解构 * a:switch只能针对某个表达式的值作 ...
- PASCAL VOC数据集分析
http://blog.csdn.net/zhangjunbob/article/details/52769381
- java基础 序列化反序列化流 实现Serializable 接口 自动装载序列号到对象文本文件如修改不能反序列化对象文本,除非自定义long型常量 打印流
package com.swift.baseKnowledge; import java.io.File; import java.io.FileInputStream; import java.io ...
- jQuery 效果使用
.hide() 隐藏匹配的元素. .hide() 这个方法不接受任何参数. .hide([duration][,complete]) duration 一个字符串或者数字决定动画将运行多久. comp ...
- Percona-Tookit工具包之pt-mext
Preface We are always obliged to analyze many outputs generated by various tools directly ev ...