2010-12-09 91 views
8

我在VS 2010中構建了一個插件,我陷入了T4代。 現在我已經實現(如MSDN建議)自定義T4主機生成我的T4結果我用它這樣:T4模板和運行時參數

 const string content = @"c:\Simple.tt"; 
     var engine = new Engine(); 
     var host = new MyTemplateHost();    
     var result = engine.ProcessTemplate(File.ReadAllText(content), host); 
     foreach (CompilerError error in host.Errors) 
     { 
      Console.WriteLine(error.ErrorText); 
     } 

這工作,直到我傳遞參數的模板。只要我在.tt文件中創建一個參數,主機就會發出警告,說它不知道如何解決它。 我看到你可以使用TemplateSession來做到這一點,但我沒有弄清楚如何將它傳遞給我的主機? 有沒有更好的方式從.tt使用C#生成代碼並在運行時傳遞參數?也許我走錯了路。

回答

12

在Visual Studio 2010中,T4模板引擎已經根本改變了。 現在你可以直接運行一個模板文件並傳給它任何參數你想要的類型。

 var template = Activator.CreateInstance<SimpleTemplate>(); 
     var session = new TextTemplatingSession(); 
     session["namespacename"] = "MyNamespace"; 
     session["classname"] = "MyClass"; 
     var properties = new List<CustomProperty> 
     { 
      new CustomProperty{ Name = "FirstProperty", ValueType = typeof(Int32) } 
     }; 
     session["properties"] = properties; 
     template.Session = session; 
     template.Initialize(); 

本聲明將處理以下模板:

<#@ template language="C#" debug="true" #> 
<#@ output extension=".cs" #> 
<#@ assembly name="System.dll" #> 
<#@ import namespace="System" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ import namespace="SampleDomain.Entities" #> 
<#@ parameter name="namespacename" type="System.String" #> 
<#@ parameter name="classname" type="System.String" #> 
<#@ parameter name="properties" type="System.Collections.Generic.List<CustomProperty>" #> 

using System; 
using System.Collections.Generic; 
using SampleDomain.Entities; 

namespace <#= this.namespacename #> 
{ 
public class <#= this.classname #> 

所以誠實是不是真的需要主機了...

+0

這代碼似乎使用preprocesed模板(如果我理解你的類型SimpleTemplate承擔。看我爲如何去使用這個內置的VS主機。 – GarethJ 2011-01-13 02:42:52

+0

非常有幫助謝謝回答。在2012年,也適用此呼叫後`Initialize()`你也可以通過檢查`template.Errors.HasErrors`來查看類型是否正確傳遞:) – 2013-11-24 12:22:39

7

如果你正在建立一個附加在VS,你可能不需要自定義主機,但可以通過其服務接口使用內置的VS主機。

退房ITextTemplating爲核心服務的API,它可以完整投放DTE對象到的IServiceProvider,然後調用GetService的(typeof運算(STextTemplating))

要傳遞的參數得到,你就可以邊拋棄的ITextTemplating對象到ITextTemplatingSessionHost並將Session屬性設置爲ITextTemplatingSession的實現。會話本質上只是一個可序列化的屬性包。有一個簡單的提供爲TextTemplatingSession

+0

謝謝,我明天必須在辦公室給它一個鏡頭。 – Raffaeu 2011-01-14 02:23:58

6

添加和落實ITextTemplatingSessionHost到自定義的主機。只是實施ITextTemplatingEngineHost不會給你會議支持。

[Serializable()] 
    public class CustomCmdLineHost : ITextTemplatingEngineHost,ITextTemplatingSessionHost 
    { 

     ITextTemplatingSession session = new TextTemplatingSession(); 

     public ITextTemplatingSession CreateSession() 
     { 
      return session; 
     } 

     public ITextTemplatingSession Session 
     { 
      get 
      { 
       return session; 
      } 
      set 
      { 
       session = value; 
      } 
     } 
1

看看MSDN Reference(「在構造函數中傳遞參數」部分)。

總結:

與TT文件同名創建一個部分類。

partial class MyWebPage 
{ 
    private MyData m_data; 
    public MyWebPage(MyData data) { this.m_data = data; }} 
} 

然後,只需將您的參數在類

MyWebPage page = new MyWebPage(data); 
String pageContent = page.TransformText(); 
4

使用T4模板的運行時生成

  1. 的構造函數,如果你需要生成你選擇這個方法代碼在運行時。例如,你想用Selenium生成一個頁面對象。

    enter image description here

  2. 在解決方案中創建一個文件夾,命名爲模板(好名字 T4模板)。

  3. 接下來添加一個T4類型的新項目,然後選擇 運行時文本模板....我們將模板MyNodeName.tt命名爲上圖中的模板。

  4. 添加您的代碼如下所示,上部是由Visual Studio插入...

Add Code

你可以看到,我們希望在命名空間和類名傳遞(這些是的Model.NameSpaceName和Model.ClassName標記上面看到的。

棘手的部分是學習如何在參數傳遞...

在文件名中創建名稱爲partial的新CS類。

Partial File Name

但在類不要將其命名MyNodeNamePartial命名MyNodeName這樣的:

public partial class MyNodeName 
    { 
     public MyNodeNameModel Model { get; set; } 
    } 

這是相同的名稱TT文件。 (MyNodeName),它創建它自己的部分類。但是現在我們看到有一個名爲這類類型的模型值..

public class MyNodeNameModel 
    { 
     public MyNodeNameModel() 
     { 
      ClassName = "Test"; 
     } 
     public string ClassName { get; set; } 
     public string NameSpaceName { get; set; } 
    } 

模型類包含類名和NameSpaceName和其他任何你想「注入」到模板。

該工作的關鍵如圖所示, 是使用運行時文本模板!如果您使用文本模板,無論您做什麼,都會看到類似「模型未找到」或其他模糊問題的錯誤。

調試提示: 「模型無法找到」是T4代代碼,告訴您在您的部分類中使用名爲MODEL的變量,它無法找到它!檢查你的部分類型和模型類型,以確保它們在相同的命名空間中,正如在該文件夾中創建的任何其他普通類名稱空間一樣。