Microsoft Developer Network > Forenhomepage > Visual Studio Extensibility > Passing parameters to Templates when programmatically generating code
Stellen Sie eine FrageStellen Sie eine Frage
 

BeantwortetPassing parameters to Templates when programmatically generating code

  • Freitag, 20. Oktober 2006 03:56Scott Simms TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     

    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);

    }

    }

    }

    }

    }

Antworten

  • Freitag, 20. Oktober 2006 22:23Gokhan Altinoren TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet
    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

Alle Antworten

  • Freitag, 20. Oktober 2006 06:31Gokhan Altinoren TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    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());
    #>:
  • Freitag, 20. Oktober 2006 08:27Scott Simms TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     

    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

     

     

     

  • Freitag, 20. Oktober 2006 22:23Gokhan Altinoren TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet
    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