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 ...
随机推荐
- python读入文档中的一行
从文件log_fusion中读入数据 方法1 f = open("log_fusion.txt") # 返回一个文件对象 line = f.readline() # 调用文件的 r ...
- 问题解决 Visual Studio 2015 无法复制文件“D:\swapfile.sys”
莫名其妙的问题..度娘 必应统统不给力.. 还是找了谷大爷 严重性 代码 说明 项目 文件 行 列 类别 源 项目级别 工具 禁止显示状态错误 无法复制文件“D:\swapfile.sys”,原因是找 ...
- 【Tim Sweeney】Why C++ for Unreal 4?
The first three generations of the Unreal Engine included a sandboxed scripting language, UnrealScri ...
- mysql数据库 thinkphp连贯操作where条件的判断不正确的问题
前两天一直写一个基于thinkphp的东西,遇到从mysql数据库里select数据,where条件一直出现问题的情况.直接上代码: $history = M('history'); $suerId ...
- java连接ssh执行shell脚本
在liunx上写了一个shell脚本,想通过java去调用这个shell脚本,不知道怎么去调用,在网上说使用process这个进程方式,但是我执行机和我shell脚本都不在同一台电脑,老大说java中 ...
- 【转】android中的Style与Theme
Android默认情况下提供了一些实用的主题样式,比如说Theme.Dialog可以让你的Activity变成一个窗口风格,而Theme.Light则让你的整个Activity具有白色的背景,而不是黑 ...
- Android Support v4,v7,v13的区别和应用场景
android-support-v4 是谷歌推出的兼容包,最低兼容Android1.6的系统,里面有类似ViewPager等控件.ViewPager在Android 1.6以下的版本是不自带的,所以要 ...
- Strut2 的 Action获取JSP 页面参数的方法
struts2 Action获取表单传值1.通过属性驱动式JSP:<form action="sys/login.action" method="post" ...
- linux中安装JDK linux中安装Tomcat linux中安装Mysql 及故障解析 linux系统安装redis
Linux 安装JDK 配置完环境变量后无法使用 java -version 无法打开 通过下面语句 将32位文件与当前系统64位兼容 (有待补充32位查法)sudo yum install glib ...
- iOS App 瘦身方案
缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...