This article describes how to use the code Wizard provided by the IWizard interface to dynamically set parameters.
Method 3: dynamically set the value using the IWizard Interface
1. First, let's take a look at the IWizard interface. This interface is first in the Microsoft. VisualStudio. TemplateWizardInterface. dll assembly. The namespace is Microsoft. VisualStudio. TemplateWizard. The signature is as follows:
1: public interface IWizard
2: {
3: void BeforeOpeningFile(ProjectItem projectItem);
4: void ProjectFinishedGenerating(Project project);
5: void ProjectItemFinishedGenerating(ProjectItem projectItem);
6: void RunFinished();
7: void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams);
8: bool ShouldAddProjectItem(string filePath);
9: }
For the time being, we will not go into depth on this interface, which is the subject of our discussion. Here we only need to know two conclusions. I will first give these two conclusions:
1) when we use the "Create Project" dialog box to create a project, and press OK, Visual Studio will instantiate the implementation of this interface (How does Visual Studio know which interface to implement the instance, and run the Runstarted method.
2) For the RunStarted method, the second parameter of this method is a Dictionary <string, string>. With this Dictionary, we can add a new Key-Value, the Key is the parameter we want to add, and the Value is the Value of the parameter we want to add, implementing the IWizard interface to dynamically set the Value.
2. We will add a TemplateWizard class library and add the EnvDTE and Microsoft. VisualStudio. TemplateWizardInterface Assembly references. This class library requires a strong signature, because it should be deployed in the GAC.
Add a DynamicCustomParameterWizard class to implement the IWizard interface. The Code is as follows:
1: public class DynamicCustomParameterWizard : IWizard
2: {
3: #region Implementation of IWizard
4:
5: public void RunStarted(object automationObject, Dictionary<string, string> replaceme
6: {
7: if (replacementsDictionary != null)
8: {
9: //$CurrentTimeWithFormat$
10: replacementsDictionary["$CurrentTimeWithFormat$"] = DateTime.Now.ToString("y
11:
12: //$AllExistingKeyValues$
13: StringBuilder stringBuilder = new StringBuilder();
14: foreach (var item in replacementsDictionary)
15: {
16: stringBuilder.Append(item.Key.PadRight(40));
17: stringBuilder.Append(item.Value);
18: stringBuilder.Append("=".PadRight(10));
19: stringBuilder.Append("\r\n");
20: }
21: replacementsDictionary["$AllExistingKeyValues$"] = stringBuilder.ToString();
22: }
23: }
24:
25: public bool ShouldAddProjectItem(string filePath)
26: {
27: return true;
28: }
29:
30: public void RunFinished()
31: {
32: }
33:
34: public void BeforeOpeningFile(ProjectItem projectItem)
35: {
36: }
37:
38: public void ProjectItemFinishedGenerating(ProjectItem projectItem)
39: {
40: }
41:
42: public void ProjectFinishedGenerating(Project project)
43: {
44: }
45:
46: #endregion
47: }
Of course, we need to create a new dynamiccustomparameterexperiment.txt,
CurrentTimeWithFormat = $ CurrentTimeWithFormat $
AllExistingKeyValues:
$ AllExistingKeyValues $
And add metadata to the project metadata file:
<ProjectItem ReplaceParameters="true">DynamicCustomParameterExperiment.txt</ProjectItem>
At this time, we should solve the previous problem. How can we make Visual Studio know that the subproject template WebClient depends on the DynamicCustomParameterWizard implementation we have defined? As we have said, the template metadata file is a link, therefore, a new node can define the implementation of this interface wizard, which is directly defined under the VSTemplate root node:
<WizardExtension>
<Assembly>Ethan.Woo.TemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e82b5e824e88ddd5</Assembly>
<FullClassName>Ethan.Woo.TemplateWizard.DynamicCustomParameterWizard</FullClassName>
</WizardExtension>
3. deployment and use: the ZIP package of the Project template is the same as before. Note that the Assembly where the interface wizard is located must be deployed in GAC, you do not need to enter this ZIP package. Since Visual Studio has limitations on the GAC deployment interface wizard assembly, isn't it a headache for our one-stop deployment? Yes, it is indeed a problem, but it can be solved. We will discuss this issue in future articles.
After deploying the ZIP package and assembly, let's take a look at the effect of the new project:
Tips: if we are developing a complex IWizard interface implementation and often need to debug the new version, it is very troublesome to manually deploy GAC, here I recommend using the Build Events mechanism (Post-build event command line ):
"C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0A \ bin \ NETFX 4.0 Tools \ gacutil.exe"/u "Ethan. woo. templateWizard, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = e82b5e1_e88ddd5"
"C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0A \ bin \ NETFX 4.0 Tools \ gacutil.exe"/I "$ (TargetPath )"
Before the end of this article, let's analyze the replacement result and draw some new conclusions:
1) when the RunStarted method starts to be executed, the parameters specified by method 1 and method 2 already have values and are placed in the Dictionary, which correspond to green and gray respectively. The blue part is obviously added dynamically in method 3. Where does the red part come from? I guess the biggest possibility is that Microsoft's MSDN does not publish or Miss system parameters.
2) since the RunStarted method published this Dictionary and has Conclusion 1, we can completely overwrite the existing parameters and values, which is useful in some special cases.
This article has already elaborated on our topic, but the discussion of IWizard is not over yet. In the next article, I will take a closer look at the IWizard interface.
From: http://www.ethan-woo.com/post/2011/05/02/VisualStudio-Template-Parameterization-Second.aspx