T4 template Visual Studio ide has more and more applications. In vs, as longCodeTo generate related scenarios, we can modify the T4 template to customize the generated format, such as the MVC view template and the entity framwork datacontext template. You can also create a T4 template file (. TT), use the C # (VB) syntax to compile the T4 template. Its syntax is similar to that of ASP. net syntax is very similar, greatly reducing. netProgramFor more information about T4 templates, please read Oleg Sych's blog about T4.Article.
T4 template, in addition to static execution output, we can also dynamically execute and output through the program. For details about how to dynamically execute the T4 template, refer to the two articles: Execute the T4 file with a program and Walkthrough: creating a custom text template host.
As mentioned in both articles, to dynamically execute the T4 template, you must define an itexttemplatingenginehost implementation class and pass it to the T4 engine during execution:
Customcmdlinehost host = new customcmdlinehost (); Engine engine = new engine (); host. templatefilevalue = templatefilename; string input = file. readalltext (templatefilename); string output = engine. processtemplate (input, host );
We can dynamically execute the T4 template. However, how do I pass parameters to the template runtime? Not mentioned in the above introduction, variables are the blood of the template engine, and the above two articles did not just introduce how to pass variables to the T4 engine context. It took several hours to finally find a clue in this blog post that the role and operating principle of the parameter statement in T4 were introduced, it also tells me how to pass parameters to the T4 engine context at runtime. To sum up, we can pass the context through the T4 template in two ways: callcontext and itexttemplatingsession. When passing objects through callcontext, note that the current host Program's execution context and T4 template engine context are different. We can use callcontext. logicalsetdata is used to pass the local object to another context. Another way is to pass the session object. The concept of this session is similar to that of ASP. the session concept of net is similar. It is an idictionary <string, Object> Object object, which allows us to define some global variables for the T4 engine context. The same problem is that in the host context, how do we pass the session to the T4 context? Read this Code:
VaR sessionhost = (itexttemplatingsessionhost) This. Host; sessionhost. Session = session;
That is, in the standard Host Object implementation, in addition to implementing itexttemplatingenginehost, you also need to implement the itexttemplatingsessionhost interface, which will have a session attribute definition. We can pass parameters by assigning values to this session. This idea can also be verified in the internal code of the engine:
Private Static void initializesessionwithhostdata (itexttemplatingenginehost host, templateprocessingsession session) {try {session. templatefile = host. templatefile;} catch (notimplementedexception) {session. templatefile = string. empty;} session. includestack. push (Session. templatefile); itexttemplatingsessionhost host2 = host as itexttemplatingsessionhost; If (host2! = NULL) {session. usertransformationsession = host2.session ;}}
Initializesessionwithhostdata is used to initialize the session data used by the engine. It checks whether the host object we passed in has implemented itexttemplatingsessionhost. If yes, the session we passed in will be used internally. After figuring out the principle, we can add the itexttemplatingsessionhost interface in the Custom itexttemplatingenginehost implementation class introduced by Walkthrough: creating a custom text template host, and then execute the T4 template, send the required parameters to the T4 engine in session mode:
[Serializable] public class parameter {public string name {Get; Set ;}} class program {static void main (string [] ARGs) {parameter = new parameter () {name = "name1"}; customtexttemplatingenginehost = new customtexttemplatingenginehost (); host. templatefilevalue = "test. TT "; engine = new engine (); string input = @ "<# @ template DEBUG =" "false" "hostspecific =" "false" "Language =" "C #" "#>< # @ output extension =" ". TXT "" #> <# @ parameter name = "" parameter1 "" type = "" t4parametersample. parameter "" #> test output, paramter name value: <# = parameter1.name #> "; host. session = new texttemplatingsession (); host. session. add ("parameter1", parameter); string output = engine. processtemplate (input, host); console. writeline (output); foreach (compilererror error in host. errors) {console. writeline (error. tostring ();} console. readline ();}}
The above implementation is to pass the parameter value in the session to the T4 template context. At the same time, we can also use callcontext to pass parameters:
Callcontext. logicalsetdata ("parameter1", parameter );
However, whether it is through session or callcontext, our host instance must implement the itexttemplatingsessionhost interface and initialize the session attribute. Otherwise, an empty reference exception occurs when this. session. containskey is called, because it checks the session for required parameter values first.
There are other ways we can achieve similar goals. For example, we can also define our own "declaration" identifiers, and then parse these "declarations" by ourselves to dynamically generate some object instances for the T4 template, but this method is more complex, technologies such as dynamic object generation and code generation are required. If you are interested, refer to: Walkthrough: creating a custom directive processor.
The example is attached.