- Visual Studio 2015高级编程(第6版)
- (美)Bruce Johnson
- 2094字
- 2021-03-19 15:26:59
15.2 扩展模板
根据现有的项或项目构建模板限制了开发人员的操作,因为它假定每个项目或场景都需要相同的项。通过少量的用户交互操作,可以将一个模板应用于多种场景,而不是为每一个不同的场景创建一个对应的模板(例如,一个场景的主窗体为黑色背景,而另一个场景的主窗体为白色背景)。因此,本节修改前面创建的项目模板,使它可以为主窗体指定背景色。
为了给模板添加用户交互操作,需要在类库中实现IWizard接口,之后在使用模板的计算机上给该类库签名,并放在全局程序集缓存(Global Assembly Cache,GAC)中。因此,要部署使用向导的模板,还需要拥有把向导程序集部署到GAC中的权限。
15.2.1 模板项目的安装
在插入和实现IWizard接口之前,执行下面的步骤,以安装解决方案。
(1)使用本章前面创建的项目模板Project Template Example创建一个新项目,命名为Extended- ProjectTemplateExample。确保这个解决方案成功生成和运行。该解决方案出现的任何问题在以后都很难检测出来,因为使用模板时出现的错误消息很难理解。
(2)在这个解决方案中添加一个Class Library项目WizardClassLibrary,在其中放置IWizard实现代码。
(3)在WizardClassLibrary中添加一个新的空类文件MyWizard和一个名为ColorPickerForm的空白Windows Form,这些文件将在以后定制。
(4)要访问IWizard接口,需要在Classic Library项目中添加对EnvDTE.dll和Microsoft. VisualStudio.TemplateWizardInterface.dll的引用。EnvDTE.dll位于%programfiles%\Common Files\Microsoft Shared\MSEnv\PublicAssemblies中,而Microsoft.VisualStudio.TemplateWizardInterface.dll位于%programfiles%\ Microsoft Visual Studio 14.0\Common7\IDE\PublicAssemblies\中。
15.2.2 IWizard
WizardClassLibrary的目的、使用IWizard接口的实际原因是给模板创建过程添加编程关联。在项目中,有一个窗体(ColorPickerForm)和一个类(MyWizard)。前者是一个简单的窗体,用于指定主窗体的背景色。对于这个窗体,需要添加一个Color Dialog控件ColorDialog1、一个Panel控件ColorPanel、一个文本为Pick Color的Button控件PickColorButton,以及一个文本为Accept Color的Button控件AcceptColorButton。完成后,ColorPickerForm应该如图15-9所示。

图15-9
在该窗体上添加如下代码。这个窗体的主要逻辑在Pick Color按钮的事件处理程序中,该按钮会打开用于选择颜色的ColorDialog。
VB
Public Class ColorPickerForm Public ReadOnly Property SelectedColor() As Drawing.Color Get Return ColorPanel.BackColor End Get End Property Private Sub PickColorButton_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles_ PickColorButton.Click ColorDialog1.Color = ColorPanel.BackColor If ColorDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then ColorPanel.BackColor =ColorDialog1.Color End If End Sub Private Sub AcceptColorButton_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles _ AcceptColorButton.Click Me.DialogResult = Windows.Forms.DialogResult.OK Me.Close() End Sub End Class
C#
using System; using System.Drawing; using System.Windows.Forms; namespace WizardClassLibrary { public partial class ColorPickerForm : Form { public ColorPickerForm() { InitializeComponent(); PickColorButton.Click += PickColorButton_Click; AcceptColorButton.Click += AcceptColorButton_Click; } public Color SelectedColor { get {return ColorPanel.BackColor; } } private void PickColorButton_Click(object sender, EventArgs e) { ColorDialog1.Color =ColorPanel.BackColor; if (ColorDialog1.ShowDialog() == DialogResult.OK) { ColorPanel.BackColor = ColorDialog1.Color; } } private void AcceptColorButton_Click(object sender, EventArgs e) { this.DialogResult =DialogResult.OK; this.Close(); } } }
MyWizard类实现了IWizard接口,用户可以通过该接口对模板进行大量的交互操作。现在,为RunStarted方法添加代码,项目创建进程在启动后会调用这个方法。然后用户就可以为主窗体选择并应用新的背景色:
VB
Imports Microsoft.VisualStudio.TemplateWizard Imports System.Windows.Forms Public Class MyWizard Implements IWizard Public Sub BeforeOpeningFile(ByVal projectItem As EnvDTE.ProjectItem) _ Implements IWizard.BeforeOpeningFile End Sub Public Sub ProjectFinishedGenerating(ByVal project As EnvDTE.Project) _ Implements IWizard.ProjectFinishedGenerating End Sub Public Sub ProjectItemFinishedGenerating _ (ByVal projectItem As EnvDTE.ProjectItem) _ Implements IWizard.ProjectItemFinishedGenerating End Sub Public Sub RunFinished() Implements IWizard.RunFinished End Sub Public Sub RunStarted(ByVal automationObject As Object, _ ByVal replacementsDictionary As _ Dictionary(Of String, String), _ ByVal runKind As WizardRunKind, _ ByVal customParams() As Object) _ Implements IWizard.RunStarted Dim selector As New ColorPickerForm If selector.ShowDialog = DialogResult.OK Then Dim c As Drawing.Color = selector.SelectedColor Dim colorString As String = "System.Drawing.Color.FromArgb(" & _ c.R.ToString & "," & _ c.G.ToString & "," & _ c.B.ToString & ")" replacementsDictionary.Add _ ("Background=""Silver""", _ "Background=""" & colorString & """") End If End Sub Public Function ShouldAddProjectItem(ByVal filePath As String) As Boolean _ Implements IWizard.ShouldAddProjectItem Return True End Function End Class
C#
using System; using System.Drawing; using System.Windows.Forms; using Microsoft.VisualStudio.TemplateWizard; namespace WizardClassLibrary { public class MyWizard : IWizard { public void BeforeOpeningFile(EnvDTE.ProjectItem projectItem) { } public void ProjectFinishedGenerating(EnvDTE.Project project) { } public void ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem) { } public void RunFinished() { } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { ColorPickerForm selector = new ColorPickerForm(); if (selector.ShowDialog() == DialogResult.OK) { Color c = selector.SelectedColor; string colorString = "Color.FromArgb(" + c.R.ToString() + "," + c.G.ToString() + "," + c.B.ToString() + ")"; replacementsDictionary.Add ("Background=""Silver""", "Background=""" + colorString + """"); } } public bool ShouldAddProjectItem(string filePath) { return true; } } }
在RunStarted方法中,提示用户可以选择一个新的颜色,然后使用产生的响应在替换词典中插入一个新的条目。在本例中,将使用由用户指定颜色的RGB值组成的连接字符串替换'Background= "silver"'。如果创建的文件需要应用于新的项目,则需要使用替换词典,因为系统可以在替换词典中搜索替换键。找到这些替换键的实例后,就用对应的替换值替代它们。在本例中搜索的是将BackColor指定为Silver值的行,然后把它替换为用户指定的新颜色。
包含IWizard接口的实现代码的类库必须包含一个能放在GAC中的强名称程序集。为此,应使用Project Properties对话框的Signing选项卡生成一个新的签名密钥,如图15-10所示。

图15-10
选择了Sign the assembly复选框后,密钥文件将没有默认值。为创建新密钥,从下拉列表中选择<New...>项。或者通过下拉列表中的<Browse...>项使用已有的密钥文件。
15.2.3 生成扩展项目模板
这个例子的模板基于ExtendedProjectTemplateExample项目,只需要进行很少的修改,刚才构建的向导就可以正确工作。前面在替换词典中添加了一项,并搜索将Background设置为Silver的实例。如果希望在使用向导时给MainWindow指定Background,就需要确保找到了替换值。为此,只需要把MainWindow的Background属性设置为Silver。这会在MainWindow.xaml文件中给Grid元素添加特性"Background = Silver",这样在替换阶段就可以找到它。
现在需要给向导关联项目模板,以便从这个模板中创建新项目。这是一个手动过程,但在项目的后续重新生成过程中进行了这些手动修改后,就可以自动完成它。首先按照前面的方法把ExtendedProjectTemplateExample导出为一个新项目模板,再在Windows Explorer中找到这个模板的.zip文件,在其中找到.vstemplate文件并编辑它,具体而言,在.vstemplate文件中添加如下代码:
<VSTemplate Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project"> <TemplateData> ... </TemplateData> <TemplateContent> ... </TemplateContent> <WizardExtension> <Assembly>WizardClassLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=022e960e5582ca43, Custom=null</Assembly> <FullClassName>WizardClassLibrary.MyWizard</FullClassName> </WizardExtension> </VSTemplate>
在示例中添加的<WizardExtension>节点表示向导的类名和它所在的强名称程序集。前面已经给向导程序集签名,所以现在只需要确定PublicKeyToken。最简单的方式是打开Visual Studio 2015命令提示符,定位到包含WizardLibrary.dll的目录。然后执行sn -T <assembly>命令。图15-11显示了该命令的输出结果。需要使用通过命令提示行找到的值替换.vstemplate文件中的PublicKeyToken值。

图15-11
现在,有一个.zip文件,其中包含项目模板,以及一个可用来扩展项目创建过程的程序集。最大的挑战是如何把这些作品交给其他人。本章一开始的模板可以通过将一个.zip文件放在合适的目录中来部署,而这个扩展模板不能。它需要把WizardLibrary.dll文件放在GAC中,而这需要一个安装程序。如何创建安装程序的详细信息参见第49章。