利用Visual Studio 2017的擴展開發(VSIX、ItemTemplate) 快速實現項目的半自動化搭建


目錄

0.引言

1.什么是Visual Studio項目模板

2.IWizad接口

3.通過Visual Studio擴展開發實現領域驅動開發

3.1 使用VSIX+ProjectTemplate創建項目模板

3.2使用ItempTemplate創建自定義項模板

3.3實現可視化添加實體字段,自動生成應用層(Dto、IAppService、AppService)、領域層(Entity)、展現層(Views、Controller)、基礎設施層(IRepository)等。

4.結語


0.引言

        最近一直在學習博客【老張的哲學】的.NET Core2.0 Api + Vue 2.0的系列文章,通過邊看邊自己動手實踐,自己對一些概念有了更深入的理解(如依賴注入、前端的一些知識、VUE框架),本來也計划好通過該系列文章好好學習一下VUE框架並應用到實際的項目中的,特此還重點突擊了一個星期左右,但最后發現自身功力不夠(畢業3年都沒有敲過代碼,加之之前只是做過一些win form的簡單開發,Web知識還是比較欠缺的,由於工作的需要今年才重新撿起來),所以是后還是放棄了。哈哈,扯遠了......下面開始進入正題

       在【老張的哲學】的系列教程第32篇博文中博主主要介紹了快速實現項目的半自動化搭建的四種方式:動軟代碼生成器、VSTO、T4模板、SqlSuagr等,按我的理解我覺得這幾種方式,無非就是事先定義好一些模板,然后按各自的方法生成相應的文件(好像這句話等於沒有說,哈哈.....),這幾種方式確實在實際的工作中可以減少很多重復性的工作,而且自己通過這大半年的開發工作中,也深有感觸是很有必要找到一種適合的方式來減少這些不必要的工作量(不瞞大家說,也不怕大家笑話,最近的項目開發中的CRUD真的是我自己一行一行敲出來的),今天的話主要在博主的基礎上在介紹另外一種方式:VSIX插件+ItemTemplate+ProjectTemplate來實現同樣的目的,這里的話主要是介紹基礎的,后面在根據項目的需要完善。本人也沒有寫過技術博客,如果寫得不好或有誤,請大家多多包含和批評指正。

1.什么是Visual Studio項目模板

       說了那么多,大家可能還是比較蒙圈(也可能是我沒有解釋清楚),直接來3張圖(如下所示),在平常的開發過程中,大家肯定經常通過在項目中右鍵創建類、接口、Windows窗體、用戶控件等,其實這些就是Visual Studio自身提供的一些模板,如新建一個Windows窗體后,窗體的大小、顏色、顯示的名稱都已經定義好了,不需要用戶在敲一大堆代碼才能把這個窗體顯示出來,本文就是通過這種方式快速實現項目的半自動化搭建。

【新建項】

【新建Windows窗體】

【Form1】

 

2.IWizad接口

       在開始操作前,首先說說“IWizard”接口:

       Visual Stdudio提供了IWizard接口,該接口提供了幾個方法幫助用戶在創建模板項時可運行自定義的代碼,見下表,本文就是通過這個接口實現的。

  Name Description
System_CAPS_pubmethod BeforeOpeningFile(ProjectItem)

Runs custom wizard logic before opening an item in the template.

System_CAPS_pubmethod ProjectFinishedGenerating(Project)

Runs custom wizard logic when a project has finished generating.

System_CAPS_pubmethod ProjectItemFinishedGenerating(ProjectItem)

Runs custom wizard logic when a project item has finished generating.

System_CAPS_pubmethod RunFinished()

Runs custom wizard logic when the wizard has completed all tasks.

System_CAPS_pubmethod RunStarted(Object, Dictionary<String, String>, WizardRunKind, Object[])

Runs custom wizard logic at the beginning of a template wizard run.

System_CAPS_pubmethod ShouldAddProjectItem(String)

Indicates whether the specified project item should be added to the project.

3.通過Visual Studio擴展開發實現領域驅動開發

3.1 使用VSIX+ProjectTemplate創建項目模板

        什么是領域驅動開發,哈哈......有興趣的可以去深入了解一下,之所以提起這個概念,主要是最近在Github上了解到ABP這個開源項目,目前start的人數多達5.5k,網址asp.net boilerplate,這個框架比較好的實現了領域驅動開發這個概念(據說也不是完全符合領域驅動設計的概念,具體的話還需要自己深入了解學習),自我認為這是個比較好的學習框架,里面涉及到比較多新的技術和知識(對於我來說基本上是新知識),大家有時間可以抽空看看,后期我也計划把該框架應用到實際的項目中去,哈哈......又扯遠了。

 下面正式進入正題:

1.創建項目模板,命名為FirstProjectTemplate。並打開該項目下的Class1.cs文件,隨意輸入一些注釋,有啥用?請耐心等待。

備注:如果沒有Extensibility這個分類,請在更新與擴展里安裝。

2.添加新的VSIX項目,命名為FirstProjectWizard,並把該項目設置為啟動項目。

3.在FirstProjectWizard項目中雙擊打開source.extension.vsixmaifest文件,填寫Product Name、Author、Version、Desription等基本信息。

4.在3打開的文件中,在左側欄中切換到Assets選項卡,單擊【New】新建一個Asset(中文不知道翻譯成啥好,哈哈...),Type選擇Microsoft.VisualStudio.ProjectTemplate,Source選擇A Project in current solution,Project選擇FirstProjectTemplate,其它設置見圖。

5.按F5 生成解決方案並啟動調試,將打開另一個Visual Studio實例(這可能需要幾分鍾的時間,電腦配置好點估計秒開...),仔細的估計會注意到Visual Studio窗口多了【實驗實例】幾個字,這個具體拿來干啥的,有興趣的可以百度一下,哈哈...

6.在剛剛打開的Visual Sdudio窗口新建一個項目,彈出的【新建項目】窗口,在右上角輸入first,選中FirstProjectTemplate,單擊確定。

7.打開剛新建項目中的Class1.cs,哦哦...剛在1步驟中注釋的語句出現了,是不是嘗到了勝利的味道。或許說到這里,大家已經大概了解到思路了,恭喜你離成功更靠近一步了....加油,請給點耐心喲。

3.2使用ItempTemplate創建自定義項模板

本節主要介紹通過自定義一些參數,實現在添加項時項模板能按要求輸出,好了...話不多說,直接演示。

1.在3.1創建的解決方案中,新建一個項項目(ItemTemplate),命名FirstItemTemplate

2.選中3.1中創建的FirstProjectWizard項目,按F4彈出屬性窗口,設置如圖三個屬性字段為ture。

3.將FirstProjectWizard、FirstItemTemplate作為Asset添加到VSIX項目中。雙擊打開source.extension.vsixmanifest 文件,並切換到Asset窗口中,相關設置見下圖。

【添加FirstProjectWizard】

【添加FirstItemTemplate】

【添加后的Asset】

4.添加VSIX開發要用到的相關類庫。在FirstProjectWizard項目下的引用鼠標右鍵,添加

EnvDTE、Microsoft.VisualStudio.TemplateWizardInterface、System.Drawing、System.Windows、System.Windows.Forms等。

5.在FirstProjectWizard項目中添加類,並命名為WizardImplementation,並繼承IWizard接口,具體代碼如下:

  1.  
    using EnvDTE;
  2.  
    using Microsoft.VisualStudio.TemplateWizard;
  3.  
    using System;
  4.  
    using System.Collections.Generic;
  5.  
    using System.Linq;
  6.  
    using System.Text;
  7.  
    using System.Threading.Tasks;
  8.  
    using System.Windows.Forms;
  9.  
     
  10.  
    namespace FirstProjectWizard
  11.  
    {
  12.  
    public class WizardImplementation : IWizard
  13.  
    {
  14.  
    private CustomFieldForm customFieldForm;
  15.  
    private string customField;
  16.  
     
  17.  
    public void BeforeOpeningFile(ProjectItem projectItem)
  18.  
    {
  19.  
     
  20.  
    }
  21.  
     
  22.  
    public void ProjectFinishedGenerating(Project project)
  23.  
    {
  24.  
     
  25.  
    }
  26.  
     
  27.  
    public void ProjectItemFinishedGenerating(ProjectItem projectItem)
  28.  
    {
  29.  
     
  30.  
    }
  31.  
     
  32.  
    public void RunFinished()
  33.  
    {
  34.  
     
  35.  
    }
  36.  
     
  37.  
    public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
  38.  
    {
  39.  
    try
  40.  
    {
  41.  
    customFieldForm = new CustomFieldForm();
  42.  
    customFieldForm.ShowDialog();
  43.  
     
  44.  
    customField = CustomFieldForm.CustomField;
  45.  
     
  46.  
    //添加自定義參數
  47.  
    replacementsDictionary.Add( "customField",
  48.  
    customField);
  49.  
    }
  50.  
    catch (Exception ex)
  51.  
    {
  52.  
    MessageBox.Show(ex.ToString());
  53.  
    }
  54.  
    }
  55.  
     
  56.  
    public bool ShouldAddProjectItem(string filePath)
  57.  
    {
  58.  
    return true;
  59.  
    }
  60.  
    }
  61.  
    }

6.在FirstProjectWizard項目中添加Windows窗體,命名為CustomFieldForm,具體代碼如下:

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.ComponentModel;
  4.  
    using System.Data;
  5.  
    using System.Drawing;
  6.  
    using System.Linq;
  7.  
    using System.Text;
  8.  
    using System.Threading.Tasks;
  9.  
    using System.Windows.Forms;
  10.  
     
  11.  
    namespace FirstProjectWizard
  12.  
    {
  13.  
    public partial class CustomFieldForm : Form
  14.  
    {
  15.  
    private static string customField;
  16.  
     
  17.  
    public CustomFieldForm()
  18.  
    {
  19.  
    InitializeComponent();
  20.  
    }
  21.  
     
  22.  
    public static string CustomField
  23.  
    {
  24.  
    get
  25.  
    {
  26.  
    return customField;
  27.  
    }
  28.  
    set
  29.  
    {
  30.  
    customField = value;
  31.  
    }
  32.  
    }
  33.  
     
  34.  
    private void button1_Click(object sender, EventArgs e)
  35.  
    {
  36.  
    customField = textBox1.Text;
  37.  
    }
  38.  
    }
  39.  
    }

7.添加程序集簽名。選中FirstProjectWizard項目,右鍵單擊,選中項目屬性,切換到簽名欄,勾選為程序集簽名,輸入秘鑰文件名稱key.snk,去掉勾選使用密碼保護秘鑰文件,相關設置見下圖。

8.選中FirstProjectWizard項目,按F4彈出屬性窗口,設置復制生成輸出到輸出目錄字段true,並重新生成解決方案。

9.將剛生成的key.snk秘鑰文件拷貝到C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools目錄下,運行cmd(需要管理員身份運行),並cd到C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools該目錄下,輸入:

sn.exe -p key.snk outfile.key

10.從key.snk中獲取公鑰,在命令窗口輸入,如圖 並記下該公鑰。

sn.exe -t outfile.key

11.將對自定義向導的引用添加到項目模板的.vstemplate 文件。分別找到FirstItemTemplate、FirstProjectTemplate項目中的兩個vstemplate文件,在<TemplateContent>節點后面添加如下代碼,最終如圖。

  1.  
    <WizardExtension>
  2.  
    <Assembly>FirstProjectWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df318ff0a21a5d6d </Assembly>
  3.  
    <FullClassName>FirstProjectWizard.WizardImplementation </FullClassName>
  4.  
    </WizardExtension>

12.保存所有文件,並重新生成解決方案。按F5運行,打開剛剛創建的FirstProjectTemplate1項目,右鍵添加新項,彈出【添加新項】窗口,在右上角搜索first,哈哈...FirstItemTemplate出現啦...成功八九十

3.3實現可視化添加實體字段,自動生成應用層(Dto、IAppService、AppService)、領域層(Entity)、展現層(Views、Controller)、基礎設施層(IRepository)等。

      好啦,通過3.1、3.2的介紹基本的框架已經搭建起來啦,下面就在ABP架構的基礎上實現通過可視化添加實體,快速自動生成領域驅動設計各層的部分文件,注意只是部分哈,不要糾結是否符合領域驅動設計

     在開始前,首先介紹一下【模板參數】,見下表,replacementsDictionary共有23個系統自帶的參數,通過鍵值(Dictionary)保存,當然用戶可以通過自定義參數添加到字典中,具體有什么作用,請見后文。

參數 描述
clrversion 公共語言運行時 (CLR) 的當前版本。
GUID [1-10] 一個用於替換項目文件中的項目 GUID 的 GUID。 可指定最多 10 個唯一的 GUID(例如,guid1)
itemname “添加新項”對話框中由用戶提供的名稱。
machinename 當前的計算機名稱(例如,Computer01)。
projectname “新建項目”對話框中由用戶提供的名稱。
registeredorganization 來自 HKLM\Software\Microsoft\Windows NT\CurrentVersion\RegisteredOrganization 的注冊表項值。
rootnamespace 當前項目的根命名空間。 此參數僅適用於項模板。
safeitemname 用戶在“添加新項”對話框中提供的名稱,名稱中移除了所有的不安全字符和空格。
safeprojectname 用戶在“新建項目”對話框中提供的名稱,名稱中移除了所有的不安全字符和空格。
time 以 DD/MM/YYYY 00:00:00 格式表示的當前時間。
SpecificSolutionName 解決方案的名稱。 在選中“創建解決方案目錄”時,SpecificSolutionName 具有解決方案名稱。 在未選中“創建解決方案目錄”時,SpecificSolutionName 為空。
userdomain 當前的用戶域。
username 當前的用戶名稱。
webnamespace 當前網站的名稱。 此參數在 Web 窗體模板中用於保證類名是唯一的。 如果網站在 Web 服務器的根目錄下,則此模板參數會解析為 Web 服務器的根目錄。
year 以 YYYY 格式表示的當前年份。

1.在FirstItemTemplate項目中,雙擊打開vstemplate文件,找到文件自動生成的<ProjectItem>,隨后跟着添加多幾個<ProjectItem>,具體如下:

  1.  
    <!--safeitemname 用戶在“添加新項”對話框中提供的名稱,名稱中移除了所有的不安全字符和空格-->
  2.  
    <ProjectItem ReplaceParameters="true" TargetFileName="$safeitemname$.cs">Core\Entity.cs </ProjectItem>
  3.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\I$safeitemname$AppService.cs">Application\IAppService.cs </ProjectItem>
  4.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$AppService.cs">Application\AppService.cs </ProjectItem>
  5.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$Dto.cs">Application\EntityDto.cs </ProjectItem>
  6.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$ListDto.cs">Application\EntityListDto.cs </ProjectItem>
  7.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\Index.cshtml">UI\Index.cshtml </ProjectItem>
  8.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\Index.js">UI\Index.js </ProjectItem>
  9.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$Controller.cs">UI\Controller.cs </ProjectItem>
  10.  
    <ProjectItem ReplaceParameters="true" TargetFileName="Temp\I$safeitemname$Repository.cs">Infrastructure\IRepository.cs </ProjectItem>

2.對照在1中添加的配置新建相應文件,如Entity.cs、IAppService.cs,最終結構見下圖。

3.利用模板參數replacementsDictionary實現自定義項模板,如Entity.cs類如下圖,其它按照自己的需求實現,思路就是用replacementsDictionary里的值進行替換,如果大家有更好的思路,歡迎大家提出。

  1.  
    using Abp.Domain.Entities;
  2.  
    using System;
  3.  
    using System.Collections.Generic;
  4.  
    using System.ComponentModel.DataAnnotations.Schema;
  5.  
    using System.Text;
  6.  
     
  7.  
    namespace $ rootnamespace$
  8.  
    {
  9.  
    [ Table("Abp$safeitemname$s")]
  10.  
    public class $ safeitemname$ : Entity< long>, IMayHaveTenant, IPassivable
  11.  
    {
  12.  
    //實現IMayHaveTenant,IPassivable
  13.  
    public virtual int? TenantId { get; set; }
  14.  
    public virtual bool IsActive { get; set; }
  15.  
     
  16.  
    //自定義的字段
  17.  
    public virtual string $customField$ { get; set;}
  18.  
    }
  19.  
    }

4.在WizardImplementation類的ProjectItemFinishedGenerating( )方法中,實現文件的放到指定的工程目錄下。PS:目前的方法比較笨,主要實現思路是先根據模板生成文件,然后Copy一份到指定的目錄,然后把源文件Delete。大家如有好的方法,請多多留言。代碼如下:

  1.  
    public void ProjectItemFinishedGenerating(ProjectItem projectItem)
  2.  
    {
  3.  
    //服務層
  4.  
    if (projectItem.Name.IndexOf( "AppService") > 0)
  5.  
    {
  6.  
    if (!projectItem.IsOpen) projectItem.Open();
  7.  
     
  8.  
    foreach ( var item in _dte.Solution.Projects)
  9.  
    {
  10.  
    var project = (Project)item;
  11.  
    //找到服務層的項目
  12.  
    if (project.Name.IndexOf( "Application") > 0)
  13.  
    {
  14.  
    bool flagAppService = false;
  15.  
    ProjectItem folder = null;
  16.  
    foreach ( var folderItem in project.ProjectItems)
  17.  
    {
  18.  
    var tmp = (ProjectItem)folderItem;
  19.  
    if (tmp.Name.IndexOf( "AppService") > -1)
  20.  
    {
  21.  
    flagAppService = true;
  22.  
    folder = tmp;
  23.  
    }
  24.  
    }
  25.  
    //不存在文件夾則創建
  26.  
    if (!flagAppService)
  27.  
    folder = project.ProjectItems.AddFolder( "AppService");
  28.  
     
  29.  
    folder.ProjectItems.AddFromFileCopy(projectPath + @"AppService\" + projectItem.Name);
  30.  
    }
  31.  
    }
  32.  
    }
  33.  
    }

5.繼續按F5運行,打開Visual Studio【實驗實例】,新建一個解決方案,包含兩個工程,如下圖:

6.在CenterInfo.Core工程中右鍵新建項,彈出添加新項對話框,找到FirstItemTemplate,命名為Depart。

7.彈出創建【Depart】實體對話框,這里主要模擬創建包含Name字段的實體類,單擊確定。

8.哇...最終生成如下圖,搞了半天就這么點東西。

4.結語

       終於寫到結語了,說實話寫個技術博客真不容易(這篇博客花了2天的時間收集資料,1天的時間自己動手實踐,然后幾個小時的時間完成編寫)......在第3小節說好的【通過Visual Studio擴展開發實現領域驅動開發】,哈哈,都是騙人的,只是為了吸引大家的眼球,好啦,坑我就挖到這里,剩下的由大家把這個坑補完。

      (后續有時間會把【通過Visual Studio擴展開發實現領域驅動開發】實現,期待着...)

 

 

出處:https://blog.csdn.net/lynchee/article/details/83065608

=======================================================================================

Visual Studio 擴展包(.vsix)制作

前言:上篇介紹了 Visual Studio擴展工具添加與卸載,本編要介紹的是Visual Studio 擴展包(.vsix)的制作。

方法:

  ①、下載並安裝Visual Studio 2010 SDK。

    vs 2010 開發工具下載SDK安裝包官方下載地址:http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=2680#instructions

    vs 2010 sp1 的SDK安裝包官方下載地址:http://www.microsoft.com/downloads/info.aspx?na=41&srcfamilyid=21307c23-f0ff-4ef2-a0a4-dca54ddb1e21&srcdisplaylang=en&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2fC%2fF%2fD%2fCFD1CDDA-3046-4D13-8A6C-793EBAFDECFE%2fVsSDK_sfx.exe

    提示:一定要注意vs 版本哦,否則會安裝失敗。

  ②、創建vsix工程配置即可。

裝完SDK之后新建項目就會看到,如圖:

點擊創建VSIX Project項目,然后進行相應的配置,選擇添加擴展的類型,路徑,以及發布版本,如下圖所示:

然后生成當前項目,就大功告成了,詳細的配置參考:http://timheuer.com/blog/archive/2010/05/03/create-vsix-files-with-visual-studio-template-deployment.aspx

這是debug目錄就會生成擴展文件,如圖:

點擊安裝成功之后,擴展插件就會出現在 vs 的擴展管理里面,點擊菜單:工具-->擴展管理,如圖:

==《完》==

 

 

出處:https://www.cnblogs.com/vipstone/archive/2012/01/31/2333022.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM