一、 操纵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,下面派生出许多的子类,代表具体的代码元素,分别有:
CodeNamespace、CodeClass、CodeInterface、CodeFunction
CodeProperty、CodeVariable、CodeDelegate、CodeStruct、CodeEnum
代表着命名空间、类、接口、函数、属性、变量、委托、结构、枚举等类型的代码元素,某个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#工程,将project的Object成员转换为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 :演示了如何向工程里添加文件,以及程序集引用,以及在工程项目的右键菜单上添加自己的菜单项