当我们使用Visual Studio来新建某个项目(Project)时,通常都会使用File –> New –> Project菜单来打开New Project(新建项目)对话框,里面列出了各种项目类型以供我们选择。大部分读者朋友都应该知道,这个对话框其实是列出了所有已经安装的项目模板,不仅如此,Visual Studio还允许用户通过File –> Export Template菜单将现有的项目导出为项目模板。
平时我们最为常见的是使用Export Template来创建单一项目的项目模板,此时使用Export Template功能就十分有效。当然,社区里也有一些工具(比如微软官方的Export Template Wizard工具)能够帮忙创建项目模板,甚至可以直接将模板压缩包文件编译成供Visual Studio 2010使用的扩展安装程序(VSIX),这样用户就可以通过VSIX直接将项目模板安装到Visual Studio 2010中。虽然社区已经提供了各种各样的创建项目模板的方法,而且网上有关项目模板创建的文章和论坛帖子也不少,但大多数都是在讨论单一项目模板的创建。本文打算从一个案例解决方案开始,边做边讨论,看看在Visual Studio 2010中是如何创建多项目(解决方案)模板的。
案例解决方案 – RainbowCMS
为了演示的需要,我随手新建了一个非常简单的面向DDD的案例解决方案:RainbowCMS。这个解决方案并没有包含任何界面,也没有提供Web Service的接口,而仅仅是实现了一个非常简单的管理客户信息的应用服务。这个解决方案主要包含如下四个项目:
- RainbowCMS.Application:此项目包含了RainbowCMS的应用服务,以及与之相关的数据传输对象
- RainbowCMS.Domain:此项目包含了RainbowCMS的领域模型、仓储接口以及与DDD相关的一些接口。为了演示需要,我只在RainbowCMS中提供了非常简单的“客户-地址”模型
- RainbowCMS.Domain.Repositories:此项目实现了针对“客户”聚合的仓储,它本身应该属于领域层的一个插件,所以最后实现的时候,是需要通过IoC注射到应用层的
- RainbowCMS.Infrastructure:此项目是整个解决方案的基础结构层,包含了一些与技术相关的基础结构,比如IoCFactory
这个解决方案所包含的项目简单地将一个面向DDD的应用程序的各个部分组织在一起(展现层除外),它仅仅用于演示Visual Studio 2010中多项目解决方案模板的创建过程,因此请读者朋友不要过分地纠结其DDD架构的实现过程。
现在,我们开始基于RainbowCMS创建多项目解决方案模板。在开始之前,请先确保你的机器装有Visual Studio 2010 SDK。
多项目解决方案模板的创建
在安装了Visual Studio 2010 SDK之后,我们就可以开始创建项目模板了。在Visual Studio 2010中选择File –> New –>Project菜单,在弹出的New Project对话框的Installed Templates下,选择Visual C#/Extensibility节点,可以看到类似如下的模板选项:
现在,让我们开始使用C# Project Template项目来创建多项目解决方案模板。
新建模板项目
在上面的New Project对话框中,选择C# Project Template,在Name文本框中输入项目名称:CMSProjectTemplate,然后单击OK按钮。此时将创建一个名为CMSProjectTemplate的解决方案:
在该解决方案中真正有意义的部分是CMSProjectTemplate.vstemplate文件,CMSProjectTemplate.ico则是今后用于显示在New Project对话框中的图标;而其它的所有文件都是用来表示一个完整的C#项目的相关文件。由于现在我们是在创建多项目解决方案的模板,所以其它的这部分文件(包括AssemblyInfo.cs、Class1.cs以及ProjectTemplate.csproj)都可以删掉。于是,我们的CMSProjectTemplate解决方案就变成了如下的结构:
更改CMSProjectTemplate.vstemplate文件
既然我们已经在解决方案中删掉了一部分内容,那么CMSProjectTemplate.vstemplate文件也要作相应的修改。首先,找到VSTemplate节点的Type属性,将其改为ProjectGroup,这一点很重要,否则今后产生的项目将不会被添加到解决方案资源管理器中;其次,将TemplateContent下所有的内容删掉,并添加一个ProjectCollection节点。更改以后的CMSProjectTemplate.vstemplate内容如下:
<?xml version="1.0" encoding="utf-8"?> <VSTemplate Version="3.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"> <TemplateData> <Name>CMSProjectTemplate</Name> <Description><No description available></Description> <Icon>CMSProjectTemplate.ico</Icon> <ProjectType>CSharp</ProjectType> <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion> <SortOrder>1000</SortOrder> <TemplateID>36e8d4bf-48bc-42c9-91ab-e45348393288</TemplateID> <CreateNewFolder>true</CreateNewFolder> <DefaultName>CMSProjectTemplate</DefaultName> <ProvideDefaultName>true</ProvideDefaultName> </TemplateData> <TemplateContent> <ProjectCollection> </ProjectCollection> </TemplateContent> </VSTemplate>
导出项目模板并添加到CMSProjectTemplate解决方案
打开RainbowCMS解决方案,然后选择File –> Export Template菜单,此时将打开Export Template Wizard对话框,在对话框中选择Project Template,表示我们要将所选的项目导出为项目模板,然后在下部的下拉框中,选择需要导出为模板的项目。在这里我们选择RainbowCMS.Application,然后单击Next按钮。
在Select Template Options页中,设置与模板有关的参数,比如模板名称和描述等,在此我们都使用默认参数,注意将Automatically import the template into Visual Studio复选框去掉,表示不需要将产生的模板直接应用到Visual Studio中。在单击Finish后,向导会直接将导出模板所在的目录以文件管理器的方式打开。
将产生的RainbowCMS.Application.zip文件解压到当前文件夹备用。
回到CMSProjectTemplate项目,在项目中创建一个CMSTemplate的目录,并在该目录下创建Application目录,通过复制/粘贴的方式将RainbowCMS.Application.zip中解压出来的文件添加到CMSProjectTemplate项目的CMSTemplate/Application目录下,之后按以下步骤操作:
- 将所有*.cs文件的编译方式改为None,否则将出现编译错误
- 将RainbowCMS.Application.csproj重命名为Application.csproj,并在MyTemplate.vstemplate中,将第一个Project节点的File属性改为Application.csproj,TargetFileName属性改为$safeprojectname$.Application.csproj。注意:这里的$safeprojectname$是项目模板的一个内置的宏,表示一个“安全”的项目名称(也就是由Visual Studio处理过的,用户在New Project对话框中输入的那个项目名称)。此外,对于单一项目模板而言,直接使用这个$safeprojectname$是没有问题的,但如果是多项目解决方案的模板,那么要在各个项目中使用这个宏,就需要一些额外操作,这部分内容会在后面介绍。有关项目模板所使用的宏,请参见:模板参数
- 将CMSTemplate\Application目录下Application.csproj以及所有C#文件中的RainbowCMS改为$safeprojectname$宏
- 修改CMSProjectTemplate.vstemplate文件,在ProjectCollection节点中添加如下代码:
<ProjectTemplateLink ProjectName="$safeprojectname$.Application"> CMSTemplate\Application\MyTemplate.vstemplate </ProjectTemplateLink>
- 在Application.csproj文件中修改RootNamespace和AssemblyName,将其改为$safeprojectname$.Application
- 经过上面的修改,CMSProjectTemplate的解决方案内容如下:
用以上相同的步骤,将RainbowCMS.Domain、RainbowCMS.Domain.Repositories以及RainbowCMS.Infrastructure项目导出成模板并添加到CMSProjectTemplate解决方案。在完成了这一系列操作之后,CMSProjectTemplate解决方案如下所示:
至此,我们已经将所需要的项目模板加入到了CMSProjectTemplate中,直接编译整个解决方案,就会在输出目录中出现一个ZIP文件,它就是Visual Studio的项目模板文件。将这个ZIP文件复制到<User_Documents>\Visual Studio 2010\Templates\ProjectTemplates\Visual C#目录下,然后在Visual Studio中使用File –> New –> Project菜单打开New Project对话框,我们就可以在Visual C#的类别下找到CMSProjectTemplate的项目模板:
选中这个模板,然后为我们新建的项目起个名字,比如CMSTest1,然后单击OK按钮,我们可以看到,一个新的解决方案被创建了,它有着下面的结构:
与我们本文开始的RainbowCMS解决方案相比,除了项目名字不同(此时是CMSTest1)以外,其它的结构完全相同。双击IoCFactory.cs文件将其打开,我们发现,IoCFactory类所在的命名空间有误,我们希望的是CMSTest1.Infrastructure,而产生的代码里却是CMSTest1.Infrastructure.Infrastructure:
namespace CMSTest1.Infrastructure.Infrastructure { public static class IoCFactory { public static T GetObject<T>() { // TODO: Implement the IoC/DI logic here. return default(T); } } }
打开CMSProjectTemplate项目下的CMSTemplate\Infrastructure.IoCFactory.cs文件,内容如下:
namespace $safeprojectname$.Infrastructure { public static class IoCFactory { public static T GetObject<T>() { // TODO: Implement the IoC/DI logic here. return default(T); } } }
看来在这里$safeprojectname$指代的是CMSTest1.Infrastructure,而不是CMSTest1。通常,我们希望$safeprojectname$在解决方案的各个项目中,都是指代用户输入的项目名称(即CMSTest1),而不是每个项目各取不同的值。这样做其实很重要:比如在指定一个项目对另一个项目的引用时,例如:CMSTest1.Domain如果需要引用CMSTest1.Infrastructure,那么就需要在Domain.csproj中的项目引用部分加入$safeprojectname$.Infrastructure,然而如果$safeprojectname$指代的是CMSTest1.Domain的话,你就无法在Domain.csproj中加入这一引用,因为它会被替换成CMSTest1.Domain.Infrastructure。要解决这个问题,我们需要使用Template Wizard。我将在下一篇文章中详细介绍Template Wizard的使用。
本文案例下载
- RainbowCMS解决方案
- CMSProjectTemplate解决方案(至目前为止,未完成)
转载至:http://www.cnblogs.com/daxnet/archive/2012/01/17/2324969.html