A simple version of the T4 code generation "framework"

Source: Internet
Author: User
Tags generator
first, the definition of T4 template and the generation of code files

Let's take a look at what the final code generation needs to define, and how the T4 template should be defined. For this framework, the generation of code structures is implemented by inheriting custom types from our custom base class template. As a demo, we define a demotemplate as follows. As you can see from the code, Demotemplate is only used to generate an empty class, and the type name is specified in the constructor.

   1: Public  class Demotemplate:template
   2:  {
   3: Public      string ClassName {get; private set;}
   4: Public      demotemplate (string className)
   5:      {
   6: This          . ClassName = ClassName;
   7:      }
   8: Public      override string TransformText ()
   9:      {
  A: this          . WriteLine (' public class {0} ', this. ClassName);
  One: this          . WriteLine ("{");
  A: this          . WriteLine ("}");
  return this          . Generationenvironment.tostring ();
  :      }
  :  }

The generation of the code is finally implemented by performing the corresponding generator, for which we define the following demogenerator. Demogenerator eventually generates three. cs files, and the code for each file is ultimately generated by the demotemplate defined above. As the following code fragment shows, the Demogenerator inherited from generator overrides the Createtemplates method and returns a Dictionary object. The key of the dictionary represents the generated file name, and value represents the corresponding Template object.

   1: Public  class Demogenerator:generator
   2:  {
   3:      protected override idictionary<string, Template> createtemplates ()
   4:      {
   5:          dictionary<string, template> templates = new dictionary<string, template> ();
   6:          templates. ADD ("Foo.cs", New Demotemplate ("Foo"));
   7:          templates. ADD ("Bar.cs", New Demotemplate ("Bar"));
   8:          templates. ADD ("Baz.cs", New Demotemplate ("Baz"));
   9: Return          templates;
  :      }
  One:  }

Finally, we execute the demogenerator in the T4 file to generate the three. cs files we need.

   1:  <#@ template hostspecific= "true" language= "C #" #>
   2:  <#@ Assembly Name= "$ (TargetDir) Artech.CodeGeneration.dll" #>
   3:  <#@ import namespace= "Artech.codegeneration" #>
   4:  <#@ output extension= ". Empty" #>
   5:  <#
   6: This  . Runcodegenerator (this. Host, New Demogenerator ());
   7:  #>

Three. cs files (Foo.cs, Bar.cs, and Baz.cs) will eventually be generated in the following manner.

ii. Transformationcontext and Transformationcontextscope

Let's take a quick look at how generator ultimately uses template to generate the corresponding text file. But before we do, let's take a look at the two types of Transformationcontext and Transformationcontextscope. As the name suggests, Transformationcontext is used to store contextual information for T4 text transformations, and transformationcontextscope is used to limit the scope of the Transformationcontext. This is the same as the transaction/transactionscope relationship.

The Transformationcontext definition is as follows: The static property current represents the present Transformationcontext, through which you can get the current texttransformation (That is, the T4 file itself corresponds to the Texttransformation object), the current texttemplatingenginehost, and the DTE and ProjectItem for T4 files.

   1: Public  class Transformcontext
   2:  {
   3: Public      static Transformcontext current {get; internal set;}
   4: Public      texttransformation transformation{get; private set;}
   5: Public      itexttemplatingenginehost Host {get; private set;}
   6: Public      DTE DTE {get; private set;}
   7: Public      ProjectItem Templateprojectitem {get; private set;}
   8:  
   9:      Internal Transformcontext (texttransformation transformation, itexttemplatingenginehost host)
  %:      {           
  One: this          . Transformation = transformation;
  A: this          . host = host;
  : This          . DTE = (DTE) ((IServiceProvider) host). GetService (typeof (DTE));
  A: this          . Templateprojectitem = this. Dte.Solution.FindProjectItem (host. TemplateFile);
  :      }
  :  
  : public      static void Ensurecontextinitialized ()
  :      {
  :          if (null = = current)
  :          {
                throw new Transformationexception ("Transformcontext is not initialized.");
  :          }
  :      }
  :  }

Transformationcontext constructors are internal, so they cannot be built directly from outside, We create it by transformationcontextscope with the following definition as the current transformationcontext. The Transformationcontextscope implements the IDisposable interface, and the current Transformationcontext in the implemented Dispose method is set to null.

   1: Public  class Transformcontextscope:idisposable
   2:  {
   3: Public      Transformcontextscope (texttransformation transformation, itexttemplatingenginehost host)
   4:      {
   5:          transformcontext.current = new Transformcontext (transformation, host);
   6:      }
   7:  
   8: Public      void Dispose ()
   9:      {
  Ten:          transformcontext.current = null;
  One:      }
  :  }

Third, Template

The logical implementation of code generation is inherited from a template type that has the following definition, and it is a subclass of Texttransformation. The core of template is the render and rendertofile method, which means that the generated code is written to the corresponding build file of the T4 file, which writes the content to a specified file. The code generated by template is obtained by calling TransformText, and the T4 object represented by the Texttransformation file itself is obtained directly through the current Transformcontext in the Render method. and calls its Wirte method to write the content.

The Rendertofile method is relatively complex because it involves generating new files. It first obtains the texttemplatingenginehost by the current Transformcontext and calculates the T4 directory, and finally resolves the final path of the generated file. File creation and content writes are implemented by calling the CreateFile method, and if source control is involved, a check out operation is also required. The newly created file is eventually added to project by the ProjectItem object that represents the T4 file.

   1: Public  abstract class Template:texttransformation
   2:  {

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.