摩诘

我思故我在 常辨而常新

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
前言:前段时间贴了两篇关于VS集成环境插件开发的一些知识,本篇讲了一些具体的应用,
也只是起个抛砖引玉的作用,因为还有许多插件开发方面的应用,需要大家自己探索了.
另外,我把插件开发的系列文章集合成了一个完整的Word文档,放在下载资源里了,方便大家查阅

VS.NET 2003集成环境插件开发指南(一)----操纵菜单

VS.NET 2003集成环境插件开发指南(二)----使用窗口


VS.NET2003插件开发-代码演示

VS.NET2003插件开发-文档

代码下载     文档下载

一、             操纵VS开发环境

VS.NET自动化模型涉及的面太广,本文只针对一些专题加以说明。

1、   利用代码模型浏览代码

l          获取代码模型对象

//获取当前正活动的文档

     Document activeDocument = applicationObject.ActiveDocument;

     if(activeDocument != null)

     {

         ProjectItem projectItem = activeDocument.ProjectItem;

         if(projectItem != null)

         {

              FileCodeModel fileCodeModel = projectItem.FileCodeModel;

              if(fileCodeModel != null)

              {

                   CodeElements codeElements = fileCodeModel.CodeElements;

                   if(codeElements != null)

                   {

                       foreach(CodeElement ce in codeElements)

                       {

                            result.AddRange(getCodeElements(ce));

                       }

                   }

              }

          }

}

说明:

上面的代码先从DTE对象(也即VS自动模型的根对象)获得当前正活动的文档对象

然后再根据文档对象获取和它关联的项目元素,这里的ProjectItem其实就是在解决方案资源管理器下面的项目文件夹对应的子项。可以是各种类型,如文件,文件夹等

再从项目元素获得关联的文件代码模型

根据文件代码模型获取其代码元素的集合CodeElementCollection,代码元素的父类为CodeElement,下面派生出许多的子类,代表具体的代码元素,分别有:

CodeNamespaceCodeClassCodeInterfaceCodeFunction

CodePropertyCodeVariableCodeDelegateCodeStructCodeEnum

代表着命名空间、类、接口、函数、属性、变量、委托、结构、枚举等类型的代码元素,某个CodeElement具体是何类型,可以根据CodeElement. vsCMElement枚举类型来判断,然后再显式转换成具体的子类即可

但是更进一步的代码元素,如函数体内的语句,好像还没有看到有方法检索。不过也可以利用一些其它的方法,比如CodeRush的程序集里面提供了一个StructuralParser程序集,用于C#的代码分析。如果谁有兴趣可以研究研究

 

l          根据具体类型检索代码元素(不再多做解释了):

         private ArrayList getCodeElements(CodeElement baseElement)

         {

              ArrayList result = new ArrayList();           

 

              switch(baseElement.Kind)

              {

                   case vsCMElement.vsCMElementNamespace:

                       CodeNamespace cn = (CodeNamespace) baseElement;

                       foreach(CodeElement element in cn.Members)

                       {

                            result.AddRange(getCodeElements(element));

                       }

                       break;

                   case vsCMElement.vsCMElementClass:            

                       CodeClass cc = (CodeClass) baseElement;

                       foreach(CodeElement element in cc.Members)

                       {

                            result.AddRange(getCodeElements(element));

                       }

                       break;

                   case vsCMElement.vsCMElementInterface:

                       CodeInterface ci = (CodeInterface) baseElement;

                       foreach(CodeElement element in ci.Members)

                       {

                            result.AddRange(getCodeElements(element));

                       }

                       break;

                   case vsCMElement.vsCMElementFunction:

                       result.Add(baseElement);

                       break;

                   case vsCMElement.vsCMElementProperty:

                       {

                            result.Add(baseElement);

                       }

                       break;

                   case vsCMElement.vsCMElementEvent:

                       {

                            result.Add(baseElement);

                       }

                       break;

                   case vsCMElement.vsCMElementDelegate:

                       {

                            result.Add(baseElement);

                       }

                       break;

                   case vsCMElement.vsCMElementStruct:

                       {

                            result.Add(baseElement);

                            CodeStruct cs = (CodeStruct) baseElement;

                            foreach(CodeElement element in cs.Members)

                            {

                                 result.AddRange(getCodeElements(element));

                            }

                       }

                       break;

                   case vsCMElement.vsCMElementEnum:

                       {

                            result.Add(baseElement);

                       }

                       break;

                   case vsCMElement.vsCMElementAttribute:

                       result.Add(baseElement);

                       break;

                   case vsCMElement.vsCMElementUsingStmt:

                       result.Add(baseElement);

                       break;

                   case vsCMElement.vsCMElementVariable:

                       result.Add(baseElement);

                       break;

 

              }

              return result;

         }

 

2、   操纵解决方案及其项目文档

l          获取当前被选中的项目

下面代码演示了鼠标点击一个项目,或项目中的子项时,如何得到该项目对象

public Project GetSelectedProject()

{

     Project project = null;

     //从被选中对象中获取工程对象

     EnvDTE.SelectedItem item = Application.SelectedItems.Item(1);

 

     if(item.Project != null)

     {//被选中的就是项目本生

         project = item.Project;

     }

     else

     {//被选中的是项目下的子项

         project = item.ProjectItem.ProjectItems.ContainingProject;

     }

     return project;

}

 

l          获取当前项目的所在目录

private string GetSelectedProjectPath()

{

         string path = "";

         //获取被选中的工程

         Project project = GetSelectedProject();

         if(project != null)

         {

                   //全名包括*.csproj这样的文件命

                   path = project.FullName;

         }

         //去掉工程的文件名

         path = Path.GetDirectoryName(path);

         return path;

}

 

l          将文件加入工程中

//获取被选中的工程

Project project = this.GetSelectedProject();

//将文件夹下的文件加入工程

project.ProjectItems.AddFromDirectory(sdir);

//将单个文件加入工程

project.ProjectItems.AddFromFile(nfile);

 

 

l          向项目中加入程序集引用

using VSLangProj;

 

private void AddReference(string assembly)

{

         Project project = GetSelectedProject();

         VSProject vsproject = null;

         if (project.Kind == PrjKind.prjKindCSharpProject)

         {

                   //工程类型为C#工程,projectObject成员转换为VSProject对象

                   vsproject = project.Object as VSProject;

         }

         if(vsproject != null)

         {

                  //获取C#工程的引用集

                   VSLangProj.References refers = vsproject.References;

                   if(refers != null)

                   {

                            //将程序集引用添加到工程中

                            refers.Add(assembly);

                   }

         }

}

 

3、   在代码编辑窗口操纵代码

这里不再详述,只是列出网上的资源,大家可以自行参考

 

二、             参考资料

http://www.knowdotnet.com/add-insmacros.html

msdn帮助目录:Visual Studio .NET-->使用 Visual Studio .NET 进行开发-->参考-->自动化与扩展性参考-->公共环境对象模型

 

三、             下载包说明:

CodeNavigator    :演示了如何通过代码模型浏览代码

GuidGen             :演示了WinForm窗口在VS.NET集成环境中的应用

MenuBrowser     :演示了工具窗口的应用以及例举菜单对象的名称

RegionsAddIn     :用于添加#Region标签,演示了如何操纵代码编辑窗口

STDTools           :演示了如何向工程里添加文件,以及程序集引用,以及在工程项目的右键菜单上添加自己的菜单项

posted on 2005-04-01 14:04  sema  阅读(10039)  评论(13编辑  收藏  举报