Passing parameters to Templates when programmatically generating code
Hi,
I am generating code within a GAT project using T4 and a DSL. Since I need a fine level of control, I have implemented an Action that takes care of the code generation programmatically.
I am wondering how I can pass a parameter to a T4 template in this case?
Here is a snippet of my Action so you can get an idea of how I'm achieving this so far.
Thanks,
Scott.
public override void Execute(){
MyModeller.ModelRoot root;
string template; string templateOutput; string dslLocation; // // Get a reference to the T4 Templating engine //ITextTemplating templateGen = (ITextTemplating) Package.GetGlobalService(
typeof(STextTemplating));dslLocation = <dsl_location>;
if (templateGen != null){
// // Generate Code. Execute the template for each Class in the model // using (Store store = new Store()){
store.LoadDomainModels(
typeof(CoreDesignSurfaceDomainModel), typeof(MyModeller.MyModellerDomainModel)); using (Transaction t = store.TransactionManager.BeginTransaction("LoadModel")){
// Load the Model
root = MyModeller.MyModellerSerializationHelper.Instance.LoadModel(store, dslLocation,
null, null); foreach (MyModeller.ModelClass type in root.Types){
template = GetFromResources(<my_embedded_template2>);
// // *** HOW DO I PASS 'type' as a parameter to this template?? //templateOutput = templateGen.ProcessTemplate(
"c:\\temp\\dummy.txt", template, null, null); // // Add the output to the solution //AddTemplateToSpecificFileInSolution(templateOutput);
}
}
}
}
}
Réponses
- I might be getting you wrong but, you already got the model loaded by the DirectiveProcessor in your template, right? (Assuming that GAT also provides the processor for your model. I know little about GAT) In the template, you can replace some %ID% placeholder with the ID of the "type", enumerate the loaded model, find your ModelClass with the %ID% supplied and process as you like.
If you absolutely need your property ready to use at the begining, you can write a custom directive processor to load your model and supply a specific object, inherited from RequiresProvidesDirectiveProcessor, but you will still need to supply a hint to find your desired class instance from the model.
You may want to look at http://msdn2.microsoft.com/en-us/library/aa397875.aspx for usage. There's also a sample @
C:\Program Files\Visual Studio 2005 SDK\2006.09\VisualStudioIntegration\Samples\DSLTools\Example.TextTemplating\Example.TextTemplating.DirectiveProcessors
if you have the SDK installed.
Gokhan
Toutes les réponses
- Hi Scott,
You may do a string replace on "template" variable. Define a placeholder variable in you template and replace it before calling ProcessTemplate.
I use the code below in a Custom Tool, not exactly the same with your code but the same approach.
internal class ActiveWriterTemplatedCodeGenerator : TemplatedCodeGenerator
{
protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
{
ResourceManager manager =
new ResourceManager("Altinoren.ActiveWriter.VSPackage",
typeof (ActiveWriterTemplatedCodeGenerator).Assembly);
FileInfo fi = new FileInfo(inputFileName);
inputFileContent =
manager.GetObject("ActiveWriterReport").ToString().Replace("%MODELFILE%", fi.Name).Replace(
"%NAMESPACE%", FileNameSpace).Replace("%EXT%", "cs"); // TODO: Get file extension from the project model
byte[] data = base.GenerateCode(inputFileName, inputFileContent);
return data;
}
}
and the template
<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" debug="true"#>
<#@ output extension=".%EXT%" #>
<#@ ActiveWriter processor="ActiveWriterDirectiveProcessor" requires="fileName='%MODELFILE%'" #>
<#@ import namespace="Altinoren.ActiveWriter.CodeGeneration" #>
<#
CodeGenerationHelper helper = new CodeGenerationHelper(this.Model, "%NAMESPACE%");
this.Write(helper.Generate());
#>: I was thinking of the situation where you have parameters defined in a template like:
<#@ property processor="PropertyProcessor" name="MyParameter" type="MyType" #>
... and you want to programmatically supply the parameters from an Action.
Thanks,
Scott
- I might be getting you wrong but, you already got the model loaded by the DirectiveProcessor in your template, right? (Assuming that GAT also provides the processor for your model. I know little about GAT) In the template, you can replace some %ID% placeholder with the ID of the "type", enumerate the loaded model, find your ModelClass with the %ID% supplied and process as you like.
If you absolutely need your property ready to use at the begining, you can write a custom directive processor to load your model and supply a specific object, inherited from RequiresProvidesDirectiveProcessor, but you will still need to supply a hint to find your desired class instance from the model.
You may want to look at http://msdn2.microsoft.com/en-us/library/aa397875.aspx for usage. There's also a sample @
C:\Program Files\Visual Studio 2005 SDK\2006.09\VisualStudioIntegration\Samples\DSLTools\Example.TextTemplating\Example.TextTemplating.DirectiveProcessors
if you have the SDK installed.
Gokhan

