目录

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.结语


文章是有图片的,如果图片打不开请访问CSDNhttps://blog.csdn.net/lynchee/article/details/83065608

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
BeforeOpeningFile(ProjectItem)

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

ProjectFinishedGenerating(Project)

Runs custom wizard logic when a project has finished generating.

ProjectItemFinishedGenerating(ProjectItem)

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

RunFinished()

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

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

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

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接口,具体代码如下:

using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace FirstProjectWizard
{
public class WizardImplementation : IWizard
{
private CustomFieldForm customFieldForm;
private string customField; public void BeforeOpeningFile(ProjectItem projectItem)
{ } public void ProjectFinishedGenerating(Project project)
{ } public void ProjectItemFinishedGenerating(ProjectItem projectItem)
{ } public void RunFinished()
{ } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
try
{
customFieldForm = new CustomFieldForm();
customFieldForm.ShowDialog(); customField = CustomFieldForm.CustomField; //添加自定义参数
replacementsDictionary.Add("customField",
customField);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} public bool ShouldAddProjectItem(string filePath)
{
return true;
}
}
}

6.在FirstProjectWizard项目中添加Windows窗体,命名为CustomFieldForm,具体代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace FirstProjectWizard
{
public partial class CustomFieldForm : Form
{
private static string customField; public CustomFieldForm()
{
InitializeComponent();
} public static string CustomField
{
get
{
return customField;
}
set
{
customField = value;
}
} private void button1_Click(object sender, EventArgs e)
{
customField = textBox1.Text;
}
}
}

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>节点后面添加如下代码,最终如图。

  <WizardExtension>
<Assembly>FirstProjectWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df318ff0a21a5d6d</Assembly>
<FullClassName>FirstProjectWizard.WizardImplementation</FullClassName>
</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>,具体如下:

    <!--safeitemname    用户在“添加新项”对话框中提供的名称,名称中移除了所有的不安全字符和空格-->
<ProjectItem ReplaceParameters="true" TargetFileName="$safeitemname$.cs">Core\Entity.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\I$safeitemname$AppService.cs">Application\IAppService.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$AppService.cs">Application\AppService.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$Dto.cs">Application\EntityDto.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$ListDto.cs">Application\EntityListDto.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\Index.cshtml">UI\Index.cshtml</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\Index.js">UI\Index.js</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\$safeitemname$Controller.cs">UI\Controller.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="Temp\I$safeitemname$Repository.cs">Infrastructure\IRepository.cs</ProjectItem>

2.对照在1中添加的配置新建相应文件,如Entity.cs、IAppService.cs,最终结构见下图。

3.利用模板参数replacementsDictionary实现自定义项模板,如Entity.cs类如下图,其它按照自己的需求实现,思路就是用replacementsDictionary里的值进行替换,如果大家有更好的思路,欢迎大家提出。

using Abp.Domain.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text; namespace $rootnamespace$
{
[Table("Abp$safeitemname$s")]
public class $safeitemname$ : Entity<long>, IMayHaveTenant, IPassivable
{
//实现IMayHaveTenant,IPassivable
public virtual int? TenantId { get; set; }
public virtual bool IsActive { get; set; } //自定义的字段
public virtual string $customField$ {get;set;}
}
}

4.在WizardImplementation类的ProjectItemFinishedGenerating( )方法中,实现文件的放到指定的工程目录下。PS:目前的方法比较笨,主要实现思路是先根据模板生成文件,然后Copy一份到指定的目录,然后把源文件Delete。大家如有好的方法,请多多留言。代码如下:

   public void ProjectItemFinishedGenerating(ProjectItem projectItem)
{
//服务层
if (projectItem.Name.IndexOf("AppService") > )
{
if (!projectItem.IsOpen) projectItem.Open(); foreach (var item in _dte.Solution.Projects)
{
var project = (Project)item;
//找到服务层的项目
if (project.Name.IndexOf("Application") > )
{
bool flagAppService = false;
ProjectItem folder = null;
foreach (var folderItem in project.ProjectItems)
{
var tmp = (ProjectItem)folderItem;
if (tmp.Name.IndexOf("AppService") > -)
{
flagAppService = true;
folder = tmp;
}
}
//不存在文件夹则创建
if (!flagAppService)
folder = project.ProjectItems.AddFolder("AppService"); folder.ProjectItems.AddFromFileCopy(projectPath + @"AppService\" + projectItem.Name);
}
}
}
}

5.继续按F5运行,打开Visual Studio【实验实例】,新建一个解决方案,包含两个工程,如下图:

6.在CenterInfo.Core工程中右键新建项,弹出添加新项对话框,找到FirstItemTemplate,命名为Depart。

7.弹出创建【Depart】实体对话框,这里主要模拟创建包含Name字段的实体类,单击确定。

8.哇...最终生成如下图,搞了半天就这么点东西。

4.结语

终于写到结语了,说实话写个技术博客真不容易(这篇博客花了2天的时间收集资料,1天的时间自己动手实践,然后几个小时的时间完成编写)......在第3小节说好的【通过Visual Studio扩展开发实现领域驱动开发】,哈哈,都是骗人的,只是为了吸引大家的眼球,好啦,坑我就挖到这里,剩下的由大家把这个坑补完。

  (后续有时间会把【通过Visual Studio扩展开发实现领域驱动开发】实现,期待着...)

利用Visual Studio 2017的扩展开发(VSIX、ItemTemplate) 快速实现项目的半自动化搭建的更多相关文章

  1. Visual Studio 2017进行Python开发环境的搭建,使用VS2017进行python代码的编写。

    Visual Studio 2017进行Python开发环境的搭建,使用VS2017进行python代码的编写. 前提:已经安装过VS2017且进行过配置. 第一部分: Python环境的搭建: 建议 ...

  2. Visual Studio 2017 针对移动开发的新特性介绍

    欢迎大家持续关注葡萄城控件技术团队博客,更多更好的原创文章尽在这里~~ Visual Studio是世界上最好的IDE之一,如果是 .NET世界,那就没有之一了(^_^),而最近推出的Visual S ...

  3. Visual Studio 2017 插件扩展

    “工具善其事,必先利其器!装好这些插件让vs更上一层楼” ReSharper : 首先的是Resharper,这个基本是目前是我开发过程中必备的工具集,唯一的缺点就是吃内存,所以你的内存要是低于8G, ...

  4. Visual Studio 2017部署 webStrom开发的nodejs项目

    vs点击文件--新建--项目--JavaScript--Node.js--通过现有Node.js代码 wxxcx为nodejs项目根目录,然后右击整个项目--属性:1.启动目录2.默认打开的链接3.设 ...

  5. Visual Studio 2017 安装后无法创建c++或MFC项目

    话话不多说,直接上图

  6. 用于Azure功能的Visual Studio 2017工具

    今天我们很高兴地宣布发布第一个预览的Visual Studio 2017工具的Azure功能.这个预览介绍了一些令人兴奋的变化,我们以前的版本.此外,除了支持Visual Studio 2017之外, ...

  7. Visual Studio 2017 调试 windows server 2016 Docker Container

    网上很多文章都是在win10下,用Docker for windows工具进行Docker的安装部署的.用知道windows server 2016已经原生支持Docker了,其windows Con ...

  8. 爆料!如何在Visual Studio 2017上体验五星级云服务

    2017 年 3 月初,号称宇宙最强 IDE 之一的 Visual Studio 发布了最新的 2017 版本,遥想自己使用 VC++ 6.0 的当年,看着现在已然稀疏的头发,真是一入 IT 似海深, ...

  9. 软件工程第2次作业——Visual Studio 2017下基于C/C++的VSTS单元测试实践

    Write one minute, test all day long. 环境确定 IDE:Microsoft Visual Studio 2017 Community 语言:C++ 单元测试工具:V ...

随机推荐

  1. .net 获取配置文件AppSettings的键值

    //AppSettings.config 节点代码 <appSettings> <add key="IsUpdate" value="false&quo ...

  2. typora画图

    https://steemit.com/utopian-io/@jubi/typora-typora-tutorial-exquisite-graph https://support.typora.i ...

  3. CentOS7使用yum安装配置Redis

    >>>>>>>>>>>>>>>>>>>>>>>>> ...

  4. SourceInSight自定义命令说明与应用

    1.自定义命名设置界面(Tool -> Custom Commands...) Command 显示当前选中命令的名字. 下拉列表中包含了所有的自定义命令. Run 命令行,当调用自定义命令时, ...

  5. git 仓库中删除历史大文件

    git 仓库中删除历史大文件 在git中增加了一个很大的文件,而且被保存在历史提交记录中,每次拉取代码都很大,速度很慢.而且用删除 提交历史记录的方式不是很实际. 以下分几个步骤介绍如何减小.git文 ...

  6. OpenCV函数学习:alignPtr对齐指针

    转载地址:https://www.tuicool.com/articles/q2QrQr 在某些架构上,只有能被指定数(如4,16)整除的内存地址才能够被访问,否则程序会crash,或者出现错误的结果 ...

  7. shell 处理小数位加减法(比较)运算

    有一个shell脚本需要处理小数位运算,刚开始使用了expr Java代码   a=7.9 b=10 c=`expr  $a \> $b` 结果运算错误,因为expr只支持整数运算,不支持小数. ...

  8. matplotlib函数理解

    cumsum(),通常用于计算一个数组各行的累加值,函数用法是B = cumsum(A,dim),或B = cumsum(A). def cumsum(self, axis=0, *args, **k ...

  9. gcd前缀和-蒜头君的数轴

    题目: 今天蒜头君拿到了一个数轴,上边有 n个点,但是蒜头君嫌这根数轴不够优美,想要通过加一些点让它变优美,所谓优美是指考虑相邻两个点的距离,最多只有一对点的距离与其它的不同. 蒜头君想知道,他最少需 ...

  10. ftp无法上传问题

    1.背景 ftp服务端和客户端一直未做任何改动,无法上传属于突发状态,除此客户端外其他客户端上传正常 客户端(SunOS系统)可以正常连接ftp的xxx21端口,但是传输数据(文件)时无法正常传输 上 ...