Visual Studio Development Bookmark and Share   
 index > Visual Studio Guidance Automation Toolkit > Executing same T4 action several times with different parameter values
 

Executing same T4 action several times with different parameter values

Hello, I need to implement the following scenario:

I want to create several files using a list of parameters retrieved from a wizard.
The problem is that i don´t know how many files i need to create, this depends on the input in the wizard.
So i need to call the same action (actually 2 actions, one to create the string with all the class code and another to insert the file in a project) several times accordingly to the number of objects in a collection retrieved from the wizard. I investigated and found several ways to achieve this goal:

Declaratively:
1 - Using a ForEach tag in the action configuration. But i didn´t find any complete example of this. Is it possible to do something like this?

<Action Name="GenerateClasses"
Type="TextTemplateAction"
Template="Text\Standard.t4"
ForEach="$(DataContractsList)"
CurrentInputName="DataContractInfo"
<Input Name="TableEntityInfo"/>
<Output Name="Content" />
</Action>

Programmatically
2 - Using an Action that receives the wizard info and calling the t4 action internally - This has a known problem related to passing arguments programmatically to a T4 template. Can anyone tell how to pass arguments from inside an Action to a T4 Action?

3 - Using directlyITextTemplatingEngine like:

string tempfile = Path.GetTempFileName();

TypeResolutionService typeResService = (TypeResolutionService)GetService(typeof(ITypeResolutionService));
Dictionary<string, PropertyData> dict = new Dictionary<string, PropertyData>();
dict.Add("ClassName", new PropertyData(modulo, typeof(string)));
host.TemplateFile = @"C:\Documents and Settings\Computer\Project\Templates\Text\Template.cs.t4";
TemplateHost host = new TemplateHost(Directory.GetCurrentDirectory(), dict);


ITextTemplatingEngine engine = new Engine();
string template = File.ReadAllText(host.TemplateFile);
stringTemplateText = engine.ProcessTemplate(template, host);

using (StreamWriter sw = new StreamWriter(tempfile, false))
{
sw.WriteLine(TemplateText);
}
EnvDTE.ProjectItem item = CreateDirectoryPresenter();
item.ProjectItems.AddFromTemplate(tempfile, "");
File.Delete(tempfile);

This last one seem the more complicated way.


Please... What is the best way to call several times a T4 Action with different parameter values?


Thank You



jrebelo  Thursday, August 21, 2008 12:33 AM
One approach that Iuse is to create a custom Action class thatderivesfromMicrosoft.Practices.RecipeFramework.VisualStudio.Library.Templates.T4Action. In doing so, I can iterate through an object and then render a template for each item in that object. It's not too messy, and this approach also allows be to combine the template rendering and the creation of the artifact file into a single action. Below is code that demonstrates my basic approach:


usingSystem;
usingSystem.Windows.Forms.Design;
usingMicrosoft.Practices.RecipeFramework;
usingSystem.Collections.Generic;
publicclassCustomTemplateAction:Microsoft.Practices.RecipeFramework.VisualStudio.Library.Templates.T4Action
{
#regionInputProperties
//Placeinputpropertieshere
#endregion
///<summary>
///Generatesatextfileinthespecifiedproject.
///</summary>
///<paramname="fileName">Nameofthefiletocreate.</param>
///<paramname="content">Contentofthetextfiletobecreated.</param>
privatevoidGenerateTextFile(stringfileName,stringcontent)
{
using(Microsoft.Practices.RecipeFramework.Library.Actions.AddItemFromStringActionmyAction=newMicrosoft.Practices.RecipeFramework.Library.Actions.AddItemFromStringAction())
{
base.Container.Add(myAction);
//setparametersforaction
myAction.Content=content;
myAction.TargetFileName=fileName;
myAction.Project=outputProject;
myAction.Execute();
}
}
///<summary>
///Rendersatemplatesandsavestoafile.
///</summary>
///<paramname="templateName">Nameoftexttemplatefile.</param>
///<paramname="fileOutput">Nameoftheoutputfiletosavethetemplateto.</param>
privatevoidGenerateTemplate(stringtemplateName,stringfileOutput)
{
//GetpathtoTemplateFile
stringnewpath=System.IO.Path.Combine(base.GetTemplateBasePath(),templateName);
//ReadalltextinTemplateFile
StringtemplateContent=System.IO.File.ReadAllText(newpath);
//Rendertemplate
try
{
stringret=base.Render(templateContent,newpath);
GenerateTextFile(fileOutput,ret);
}
catch(Microsoft.Practices.RecipeFramework.VisualStudio.Library.Templates.TemplateExceptionte)
{
//Templateerror
}
catch(Exceptione)
{
//Otherexception
}
}
publicoverridevoidExecute()
{
//Thisarugmentwillbeavailabletoeverytexttemplate
base.additionalArguments.Add("Argument1",SomeArugment);
foreach(StringcinListOfClassesObject)
{
base.additionalArguments.Add("MyClass",c);
GenerateTemplate(TemplateName,c+".txt");
//RemoveMyClasssonextiteartion of the loop gets
//anewMyClassparameter
base.additionalArguments.Remove("MyClass");
}
}
publicoverridevoidUndo()
{
}
}
}
Clay Smith  Tuesday, August 26, 2008 6:52 PM

You can use google to search for other answers

Custom Search

More Threads

• Generic argument types
• Add .CS file to a Project
• How to generate class file from t4 template into a sub-folder under project
• Guidance Automation Extensions Registration does not work
• MetaGuidancePackage error when creating a new Guidance Package or Solution
• Analysis Services Guidance Package
• WizardPage doesnot load
• Guindance automation toolkit and extensions for Vs 2008 and Vs 2005
• Debug.WriteLine not allowed in custom TypeConverter?
• Change the solution path