2010-02-21 97 views
20

我們正在構建一個內部應用程序,需要生成HTML文件以上傳到eBay列表。我們正在尋找使用模板引擎來生成基於我們預先定義的數據庫和靜態字段的HTML文件。該模板還需要具有邏輯功能(如果 - 然後,foreach等)。在運行時創建T4模板(構建時)?

我們已經看過T4並且看起來很完美,但是我們沒有看到它是否具有在運行時使用的功能,因此用戶可以創建T4模板,然後應用程序可以「編譯「它並生成最終的HTML文件。這是可能的,以及如何?

如果沒有,我們應該看到的其他框架是否具備所有這些功能?

回答

16

我有一套類似的類,我用它來將模板文本生成嵌入到軟件中。

基本上,它的工作原理類似於舊式ASP,您在<%...%>塊中環繞C#代碼,並且可以使用<%= expression %>發出結果。

您可以將單個對象傳遞給模板代碼,這當然可以是任何您喜歡的對象類型,或者只是一組參數。如果你想執行自定義代碼,你也可以引用你自己的程序集。

下面是如何發光的一類看起來:

<% 
var parameters = (string[])data; 
var namespaceName = parameters[0]; 
var className = parameters[1]; 
%> 
namespace <%= namespaceName %> 
{ 
    public class <%= className %> 
    { 
    } 
} 

你可以通過東西當然循環:

<% foreach (var parameter in parameters) { %> 
<%= parameter %> 
<% } %> 

,並把代碼中,如果塊等

類庫在CodePlex上發佈:

以及NuGet

該項目帶有例子,下載源或browse it online

要也在這裏回答問題的電子郵件,給別人看的:

  1. 所有類型的C#代碼適合進入一個方法調用可以在模板中進行編譯。它運行正常的C#3.5代碼,這意味着一切都沒有人爲的限制。只有要知道的是,任何if,while,for,foreach等包含模板代碼的代碼都必須使用大括號,因此不能執行單行if-then類型塊。請參閱下面的方法調用限制。
  2. data參數對應於從應用程序傳入的.Generate(x)方法的參數,它是相同類型的參數。如果您傳入的是您自己的類庫中定義的對象,則需要添加對模板代碼的引用才能正確訪問它。(<%@ reference your.class.library.dll %>
  3. 如果您重新使用編譯的模板,它實質上只是一個方法調用的類,沒有額外的開銷在.Generate()的實際調用上完成。如果你自己不打電話.Compile(),第一個電話.Generate()將照顧它。另請注意,代碼在單獨的appdomain中運行,因此與複製參數和結果來回有關的編組開銷會很小。但是,代碼以正常的JITted .NET代碼速度運行。

    <% if (a == b) { %> 
    This will only be output if a==b. 
    <% } %> 
    

    有在任格式的代碼沒有人爲限制,選擇最適合您的風格:如果塊

<% 
    if (a == b) 
    { 
%> 
This will only be output if a==b. 
<% 
    } 
%> 

只有注意,所有非模板的代碼部分幾乎都會按原樣輸出,這意味着將會輸出選項卡以及以下%>塊。

有一個限制,您編寫的所有代碼必須適合單個方法調用。

讓我解釋一下。

模板引擎的工作方式是,它會產生一個cs文件,將其提供給C#編譯器,這個.cs文件roughyly看起來是這樣的:

using directives 

namespace SomeNamespace 
{ 
    public class SomeClass 
    { 
     public string Render(object data) 
     { 
      ... all your code goes here 
     } 
    } 
} 

這意味着你不能定義新類,新方法,課程級別字段等。

但是,您可以使用匿名代理在內部創建函數。舉例來說,如果你想設置日期格式的統一方式:

Func<DateTime, string> date2str = delegate(DateTime dt) 
{ 
    return dt.ToString("G"); 
}; 

那麼你可以簡單地使用模板代碼的其餘部分:

<%= date2str(DateTime.Now) %> 

唯一的要求我的是,你不」將文件上傳到網絡上,並聲稱你編寫了代碼,除此之外你可以自由地做你想做的事情。

編輯23.04.2011:與CodePlex項目的固定鏈接。

+0

Wooow O.o我現在正在下載這個,我會讓你知道它是怎麼回事。如果它做到了你所說的一切,那麼你將成爲絕對的生命保護者! – Amberite 2010-02-21 22:36:44

+0

現在編輯答案,正如您在電子郵件中所述,「數據」變量不存在,因爲它被命名爲「數據」。這是一個方法參數,因此是小寫的「d」。 – 2010-02-22 06:23:01

+0

「模板引擎的工作方式是它生成一個.cs文件並將其提供給C#編譯器」:這不就意味着運行它的機器需要安裝VisStudio或至少安裝了其他東西嗎?或者有沒有一種方法可以通過編程方式調用C#編譯器?我沒有想到編譯器與.net運行時一起提供......雖然由於IIS可以在運行中編譯ASP.NET,我猜它一定在那裏... – CodingWithSpike 2010-02-22 21:06:12

3

可以使用TextTransform.exe命令行工具編譯T4模板。你可以讓你的應用程序創建一個.tt文件,然後調用TextTransform.exe來生成輸出。

+0

是否需要使用此解決方案將Visual Studio安裝在用戶的計算機上?這對我們來說是一個限制。 – Amberite 2010-02-21 22:09:31

+0

Mono具有相當強大的文本轉換實現。我會看看,如果依賴是一個問題。 – 2010-02-21 22:17:22

+2

是的,現在,它依賴於Visual Studio。這將隨着VS2010/.NET 4和所謂的預編譯的T4模板而改變。看到這裏的信息:http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/ – 2010-02-22 06:09:55

6

實現T4文本轉換的程序集是Microsoft.VisualStudio.TextTemplating.dll,隨附Visual Studio。

如果你想從第一原則開始,你需要實現Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost,並將你的實現作爲參數傳遞給Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate(),它將執行轉換。

這比給TextTransform.exe打電話提供了更大的靈活性。

但是,如果您的代碼是發貨產品,則不清楚此程序集的許可是什麼,以及您是否有權將其重新分發給您的應用程序。

重新分發此程序集可以避免安裝Visual Studio。

+0

不幸的是,由於授權問題,這不符合我們的需求,因爲此產品將被運送給最終用戶。謝謝:) – Amberite 2010-02-24 00:06:00

+1

Mono項目也有一個開源的實現。 http://anonsvn.mono-project.com/viewvc/trunk/monodevelop/main/src/addins/TextTemplating/ – 2010-06-14 20:01:35

3

在運行時完全可以使用T4。

在.NET 3.5中,Microsoft並沒有真正以任何合理的方式支持這種情況。聽起來.NET 4.0將得到微軟的更好支持。

單聲道在.NET 3.5中爲此場景提供了一些支持。

我與.NET 3.5從單T4實施成功的幫助了證明這個概念,而是一個關閉這個問題.NET 3.5的現成的解決方案將需要比我迄今投入一噸多的努力。

您可以找到單聲道T4執行此:

https://github.com/mono/monodevelop/tree/master/main/src/addins/TextTemplating

我已經證明了一些我遇到嘗試運行從這裏.NET代碼T4模板的問題:

Options for running T4 templates from .NET code

14

如果您可以使用Visual Studio 2010進行模板創建和編輯,那麼您可以使用預編譯模板,這些模板專門針對此場景而設計,並且是Microsoft支持的選項。

你設計的模板在Visual Studio中,預編譯,並部署對Visual Studio的不依賴與應用程序一起組裝。

http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/

0

一個錯誤,我做我是加了「文字模板」文件。要在運行時間生成文本,請選擇「預處理文本模板」。如果您最初選擇了「文本模板」,將自定義工具設置爲VS中的文件屬性中的「TextTemplatingFilePreprocessor」是一個簡單的更改。