程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Visual Studio 2008可擴展性開發(五):操作Solution、Project和ProjectItem

Visual Studio 2008可擴展性開發(五):操作Solution、Project和ProjectItem

編輯:關於.NET

前言

說真的,前面幾篇隨筆讀起來會很乏味,寫起來更是如此。不過好戲總在後頭,從這 一篇開始我將介紹在Add-In中對VS的各個元素進行操作,這些會有意思得多。

大多數時候,我們在VS中進行開發,都是從打開解決方案開始,然後找到項目、打開 文件進行開發。本文將介紹與此相關的內容。

解決方案、項目和項簡介

我相信,這三者對我們.NET開發人員來說是再熟悉不過的了。但它們在AOM(自動化對 象模型)的表示方式跟我們想象的會不太一樣。看下面的圖1,其中涉及的主要元素有解 決方案、解決方案文件夾、項目、文件夾、文件。AOM通過Solution接口表示解決方案; Project接口表示解決方案文件夾和項目;ProjectItem接口表示文件夾和文件。下面我會 通過一個例子來介紹它們。

簡單的代碼生成器  

在實際開發中,我們往往需要采用一些特定的技術方案,這些方案就決定了程序的整 體架構,表現在程序中就是一些項目、程序集、配置文件的組織。曾經有段時間很喜歡 iBATIS.NET,這裡就以它的示例項目NPetshop為例進行演示。NPetshop的基本結構如下:

圖1:NPetshop的程序結構

它的代碼可以在NPetshop Source for .NET 2.0一文中找到。External-bin裡面是所 需要的各個程序集,Domain是實體類,Persistence是數據訪問層,Service是業務邏輯層 ,Presentation是表現邏輯層,Web則負責最終的表現。如果要采用這樣的解決方案進行 開發,那麼在項目開始我們就得花些時間來搭建整個解決方案的框架。通過Add-In,我們 可以做到“一次編寫,多次使用”。

現在來看看如何從零開始創建一個解決方案。在本例中,大致過程是:

圖2:解決方案創建過程

下面就來一步步實現。

0)添加命令

在之前的隨筆已經向NEnhancer添加了兩個命令了,現在需要添加新的命令,這樣重復 代碼又得多一些了,所以在添加命令之前,先將代碼重構一下,提取出幾個小方法:

C# Code - Connect類的輔助方法

private string GetCulturedMenuName(string englishName)
{
    string result = englishName;

    try
    {
        string resourceName;
        ResourceManager resourceManager = new ResourceManager ("NEnhancer.CommandBar", Assembly.GetExecutingAssembly());
        CultureInfo cultureInfo = new CultureInfo (_applicationObject.LocaleID);

        if (cultureInfo.TwoLetterISOLanguageName == "zh")
        {
            System.Globalization.CultureInfo parentCultureInfo = cultureInfo.Parent;
            resourceName = String.Concat(parentCultureInfo.Name, englishName);
        }
        else
        {
            resourceName = String.Concat (cultureInfo.TwoLetterISOLanguageName, englishName);
        }

        result = resourceManager.GetString(resourceName);
    }
    catch
    {
        result = englishName;
    }

    return result;
}

private string GetCommandFullName(string cmdName)
{
    return "NEnhancer.Connect." + cmdName;
}

private CommandBar GetCommandBarByName(string cmdBarName)
{
    return ((CommandBars)_applicationObject.CommandBars)[cmdBarName];
}

private void AddNamedCommand2(CommandBar cmdBar, string cmdName, string buttonText, string toolTip,
    bool useMsoButton, int iconIndex, int position)
{
    // Do not try to add commands to a null bar
    if (cmdBar == null) { return; }

    // Get commands collection
    Commands2 commands = (Commands2)_applicationObject.Commands;
    object[] contextGUIDS = new object[] { };

    try
    {
        // Add command
        Command command = commands.AddNamedCommand2(_addInInstance, cmdName, buttonText, toolTip,
            useMsoButton, iconIndex, ref contextGUIDS,
            (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled,
            (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
        if (command != null && cmdBar != null)
        {
            command.AddControl(cmdBar, position);
        }
    }
    catch (ArgumentException)
    {
        // Command already exists, so ignore the exception.
    }
}

有了這些方法,再添加命令就變得更簡單:

C# Code - 添加命令

OnConnection()
{

    AddNamedCommand2(toolsPopup.CommandBar, NPETSHOP_SLN_GENERATOR_COMMAND_NAME, "Generate NPetshop Sln",
        "Generate NPetshop Solution", true, 59, toolsPopup.Controls.Count + 1);

}

QueryStatus()
{

    else if (commandName == GetCommandFullName (NPETSHOP_SLN_GENERATOR_COMMAND_NAME))
    {
        status = (vsCommandStatus) vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
        return;
    }
}

Exec()
{

    else if (commandName == GetCommandFullName (NPETSHOP_SLN_GENERATOR_COMMAND_NAME))
    {
        GenerateNPetshopSln();

        handled = true;
        return;
    }
}

1)創建解決方案 

唯一需要用戶輸入的信息是解決方案的名稱(這裡假定各項目的名稱都以此為前綴) 和目錄,這需要創建一個簡單的窗體(NPetshopSlnGenerator)來收集信息。

圖3:Generator窗體

在AOM中,表示解決方案的類型是EnvDTE.Solution(以及其後續版本Solution2、 Solution3),它的重要方法和屬性有:

AddFromFile():添加既有項目;

AddFromTemplate():根據指定項目模板添加新的項目;

AddSolutionFolder():添加解決方案文件夾;

Close():關閉解決方案;

Create():創建一個空的解決方案;

Open():打開一個解決方案;

Remove():移除一個項目;

SaveAs():保存解決方案;

FileName:解決方案文件名;

FullName:解決方案文件全名;

IsOpen:表示解決方案是否已打開;

Projects:解決方案內的項目集合;

SolutionBuild:用於管理解決方案的Build過程。

Solution的完整成員列表請參看MSDN。要訪問VS中的當前解決方案,可使用 DTE.Solution屬性,下面是創建解決方案的代碼:

C# Code - 創建解決方案

Solution3 sln = (DTEObject.Solution as Solution3);
sln.Create(currentSlnPath, slnName);

一旦調用了Create方法,VS就會打開新創建的解決方案。

2)創建解決方案文件夾

在這一步,首先要把所需的程序集等文件拷貝到新解決方案所在目錄,然後創建解決 方案文件夾,將文件添加進去:

C# Code - 創建SolutionFolder

Project sfProj = sln.AddSolutionFolder(ExternalBinDirectoryName);
foreach (string file in Directory.GetFiles(ExternalBinPath))
{
    sfProj.ProjectItems.AddFromFile(file);
}

很簡單,就是調用AddSolutionFolder方法。可以看到,解決方案文件夾被看作是一種 Project,通過其ProjectItems添加文件(關於Project的更多內容請看下面)。

3)創建各個項目

由於項目之間會有依賴關系,所以考慮按依賴關系進行創建,也就是Domain- >Persistence->Service->Presentation->Web。

表示項目的類型為EnvDTE.Project,它的主要方法和屬性有:

Delete():將項目從解決方案內移除;

Save():保存項目;

SaveAs():保存解決方案、項目和文件項;

FileName/FullName:項目文件的名稱/全名;

Kind:表示項目類型的GUID值;

ProjectItems:項目所包含的項的集合;

Project的完整成員列表請參看MSDN。創建Domain項目的代碼大致如下:

C# Code - 創建項目

string classLibProjTemplatePath =
    sln.GetProjectTemplate("ClassLibrary.zip", "CSharp");
string domainProjName = slnName + "." + "Domain";
sln.AddFromTemplate(classLibProjTemplatePath, Path.Combine(currentSlnPath, domainProjName),
    domainProjName, false);
Project domainProj = GetProjectByName(sln, domainProjName);
VSProject vsDomainProj = domainProj.Object as VSProject;
vsDomainProj.References.Add(Path.Combine(ExternalBinPath, "IBatisNet.Common.dll"));

Domain是類庫項目,它有對應的項目模板,此時可以使用 Solution.GetProjectTemplate方法獲取模板路徑,然後使用AddFromTemplate方法添加項 目。本來AddFromTemplate方法返回一個Project對象,按道理應該就是新創建的項目,但 是MSDN上說對於C#和VB.NET項目來說,返回值為null!只好自己寫一個方法 GetProjectByName了,也就是循環各個項目,根據名稱找到匹配的項目。最後,要給 Domain項目添加對IBatisNet.Common.dll的引用,這裡要使用VSProject的References集 合來添加。

接下來是Persistence項目,過程與Domain基本相同,但是要給它添加對Domain項目的 引用,此時應使用References.AddProject方法:

C# Code - 添加項目引用

vsPersistProj.References.AddProject(domainProj);

照這樣下去,剩下的Service、Presentation、Web項目也可以順利創建,只是在創建 Web項目的時候要用WebApplication項目模板:Solution.GetProjectTemplate ("WebApplicationProject.zip", "CSharp")。

4)創建文件夾和文件

在AOM中,文件夾和文件統一表示為ProjectItem類型。它的主要方法和屬性為:

Delete():從項目中刪除該項;

ExpandView():展開解決方案管理器來顯示該項;

Open():打開該項;

Remove():從該項所包含的項中移除一項;

Save()/Save():保存

Kind:該項的類型;

Name:該項的名稱;

ProjectItems:該項所包含的其它項;

ProjectItem的完整成員列表請參看MSDN。Project接口有一個ProjectItems集合屬性 ,可以訪問項目所包含的項,同時該屬性還可用來添加新的項。在本例中,要添加幾個文 件夾和文件:

C# Code - 添加文件夾和已有文件

webProj.ProjectItems.AddFolder("Maps", Constants.vsProjectItemKindPhysicalFolder);
webProj.ProjectItems.AddFromFileCopy(
    Path.Combine(GetAddinPath(), @"ibatis-config\dao.config"));

這裡使用了AddFolder和AddFromFileCopy方法。如果需要添加新的文件,也很簡單, 類似於項目,這裡要使用項模板:

C# Code - 根據模板添加文件

string templatePath =
    sln.GetProjectItemTemplate("Interface.zip", "CSharp");
webProj.ProjectItems.AddFromTemplate(templatePath, "MyInterface.cs");

關於ProjectItems的更多信息請參看這裡。至此我們就完成了一個具備初步功能的代 碼生成器。

文中示例的代碼可以從這裡下載。

我們身在何處?

在VS中,解決方案、項目和文件(夾)是其基本組織形式,也是我們開發人員最為熟 悉的元素了,本文介紹的就是與此相關的基本操作。這些操作是通過開發一個具備初步功 能的代碼生成器來演示的,其中可以了解如何從解決方案開始,自上而下逐步生成項目、 文件夾和文件。但是需要說明的是,這裡沒有對Solution Explorer的操作,也沒有涉及 到對文件內容的操作,這些都將在後續的隨筆中介紹。

出處:http://www.cnblogs.com/anderslly/archive/2009/03/15/vs-addin- solution-project.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved