深入IWizard接口(上)
这篇文章,我们来研究一下IWizard这个接口。
一,一个用来跟踪的接口实现LifeCycleTracerIWizard。
因为IWizard接口是Visual Studio来管理实例化和执行方法的,也就是说它的类型实例的生命周期不是我们能够控制的,那么我们可以换一种思路来探讨这样的生命周期,所以我定义这样的一个IWizard实现LifeCycleTracerIWizard,用来跟踪接口里各个方法的执行循序,以及上下文信息,即参数值。
LifeCycleTracerIWizard.cs的代码如下:
1: public class LifeCycleTracerIWizard : IWizard
2: {
3: private string loggerFilePath = @"D:\LifeCycleTracerWizard.log";
4: private string safeProjectName = "[None]";
5:
6: public virtual String WizardType
7: {
8: get { return "LifeCycleTracerIWizard"; }
9: }
10:
11: private void LogWizardMethodAction(string methodAction)
12: {
13: using (StreamWriter streamWriter = new StreamWriter(loggerFilePath,true))
14: {
15: streamWriter.WriteLine(WizardType.PadRight(30) + "-" + safeProjectName.PadRight(15) + ":" + methodAction);
16: }
17: }
18:
19: #region Implementation of IWizard
20:
21: public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
22: {
23: if(replacementsDictionary != null && replacementsDictionary.ContainsKey("$safeprojectname$"))
24: {
25: safeProjectName = replacementsDictionary["$safeprojectname$"];
26: }
27:
28: LogWizardMethodAction("RunStarted : " + runKind);
29: }
30:
31: public void ProjectFinishedGenerating(Project project)
32: {
33: LogWizardMethodAction("ProjectFinishedGenerating");
34: }
35:
36: public void ProjectItemFinishedGenerating(ProjectItem projectItem)
37: {
38: LogWizardMethodAction("ProjectItemFinishedGenerating");
39: }
40:
41: public bool ShouldAddProjectItem(string filePath)
42: {
43: LogWizardMethodAction("ShouldAddProjectItem : " + filePath);
44: return true;
45: }
46:
47: public void BeforeOpeningFile(ProjectItem projectItem)
48: {
49: LogWizardMethodAction("BeforeOpeningFile");
50: }
51:
52: public void RunFinished()
53: {
54: LogWizardMethodAction("RunFinished");
55: }
56:
57: #endregion
58: }
二,用LifeCycleTracerIWizard跟踪多项目模板的子项目。
我们修改上一篇文章中的VSTemplate-WizardExtension-FullClassName子节点值为:Ethan.Woo.TemplateWizard.LifeCycleTracerIWizard,部署后新建实例,查看生成的Log文件“D:\LifeCycleTracerWizard.log”内容:
从结果可以看出以下几点结论:
1)确实是模板元数据文件中指定的Ethan.Woo.TemplateWizard.LifeCycleTracerIWizard接口实现被实例化了。
2)各个方法执行的顺序依次为:RunStarted->ShouldAddProjectItem->ProjectFinishedGenerating->RunFinished,这里注意一下,有两个方法没有执行到,ProjectItemFinishedGenerating是用于项模板向导的,所以这里肯定不会执行;BeforeOpeningFile这个方法也没有执行,因为它在我们制作 Starter Kit的时候才会用到,所以以后会再次讲到这个话题。
3)RunStarted这个方法的第三个参数是一个WizardRunKind枚举(有三个值:AsMultiProject,AsNewItem,AsNewProject),这里跟踪到的值是AsNewProject,表示新建一个项目。
4)ShouldAddProjectItem这个方法执行了多次?是的,我们的项目源里的项目包含了多个子文件,所以,这里明显是在模板实例化阶段,添加每个子文件时调用的,而且它有一个Boolean返回值,表示十分要添加当前的子文件到项目实例中。
三,用多个IWizard接口实现跟踪多项目模板的子项目。
先摘一段来自MSDN的原文:
Visual Studio supports chaining, which enables a single template to have multiple IWizard implementations. These implementations are called sequentially, so you can create templates that have rich, flexible functionality.
A Microsoft-implemented VsTemplate wizard is invoked to process a template by reading its .vstemplate file. A VsTemplate can list one or more assemblies that have an IWizard implementation that will be called to participate in processing the template. To take advantage of chaining, all the wizards must be listed in the template's .xml file in the order in which they should be called.
意思是说:Visual Studio支持单模板的IWizard接口实现的串联,并且是顺序执行的,还能推断出VSTemplate这个节点可以包含多个WizardExtension的设置,实现这样的一种串联。
这里我们新定义一个ChainingLifeCycleTracerIWizard接口实现,继承之前的LifeCycleTracerIWizard;
1: public class ChainingLifeCycleTracerIWizard : LifeCycleTracerIWizard
2: {
3: public override string WizardType
4: {
5: get
6: {
7: return "ChainingLifeCycleTracerIWizard";
8: }
9: }
10: }
然后,我们将这个ChainingLifeCycleTracerIWizard和之前的LifeCycleTracerIWizard一起串联到WebClient项目的模板中,当然了,还是通过模板元数据文件,注意这里的声明的顺序;
1: <VSTemplate xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Version="3.0.0" Type="Project">
2: 。。。此处省略。。。
3: <WizardExtension>
4: <Assembly>Ethan.Woo.TemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e82b5e824e88ddd5</Assembly>
5: <FullClassName>Ethan.Woo.TemplateWizard.LifeCycleTracerIWizard</FullClassName>
6: </WizardExtension>
7: <WizardExtension>
8: <Assembly>Ethan.Woo.TemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e82b5e824e88ddd5</Assembly>
9: <FullClassName>Ethan.Woo.TemplateWizard.ChainingLifeCycleTracerIWizard</FullClassName>
10: </WizardExtension>
11: </VSTemplate>
最后我们看看Log文件“D:\LifeCycleTracerWizard.log”内容:
是不是很有意思,都执行了一遍哦,不用解释了吧。
摘自:http://www.ethan-woo.com/post/2011/05/03/Deep-into-IWizard-First.aspx