首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 動態生成靜態頁面:高效能模板引擎 TextTemplate 實作詳解

     編輯:關於C語言

靜態頁面生成可減輕資料庫負載、利於 SEO。本文介紹一個輕量級模板引擎 TextTemplate,採用預先分析模板、分割為靜態片段與標記陣列的策略,渲染時僅做字串拼接,效能遠優於重複 Replace。

核心設計理念

  • 模板語法:{TagName} 為預留位置。
  • 初始化階段:用 Regex 找出所有標記,將模板切割為 _contentParts (靜態字串) 與 _tags (標記資訊) 陣列。
  • 渲染階段:依序拼接 `contentParts[0] + value[tag0] + contentParts[1] + value[tag1] ...`,無需再解析模板。

TextTemplate 類別完整實作 (精簡版)


public class TextTemplate
{
    private readonly string[] _contentParts;
    private readonly TextTemplateTag[] _tags;
    private readonly int _tagCount;

    // 內部標記結構
    private class TextTemplateTag
    {
        public string Name { get; }
        public int Position { get; }
        public int Length { get; }
        public TextTemplateTag(string name, int pos, int len)
        { Name = name; Position = pos; Length = len; }
    }

    // 從字串建構
    public TextTemplate(string content) => Parse(content);

    // 從檔案建構 (支援編碼)
    public TextTemplate(string filePath, Encoding encoding)
    {
        using (var sr = new StreamReader(filePath, encoding))
            Parse(sr.ReadToEnd());
    }

    private void Parse(string content)
    {
        var matches = Regex.Matches(content, @"\{\w+\}");
        _tagCount = matches.Count;
        _tags = new TextTemplateTag[_tagCount];
        _contentParts = new string[_tagCount + 1];

        int start = 0;
        for (int i = 0; i < _tagCount; i++)
        {
            var m = matches[i];
            _tags[i] = new TextTemplateTag(
                m.Value.Substring(1, m.Value.Length - 2), // 去掉 { }
                m.Index, m.Length);
            _contentParts[i] = content.Substring(start, m.Index - start);
            start = m.Index + m.Length;
        }
        _contentParts[_tagCount] = content.Substring(start);
    }

    // 依 Hashtable 鍵值渲染
    public string Render(Hashtable values)
    {
        var sb = new StringBuilder(8192);
        for (int i = 0; i < _tagCount; i++)
        {
            sb.Append(_contentParts[i]);
            object val = values[_tags[i].Name];
            sb.Append(val?.ToString() ?? $"{{{_tags[i].Name}}}"); // 找不到保留原標記
        }
        sb.Append(_contentParts[_tagCount]);
        return sb.ToString();
    }

    // 依參數順序渲染
    public string Render(params object[] args)
    {
        var sb = new StringBuilder(2048);
        for (int i = 0; i < _tagCount; i++)
        {
            sb.Append(_contentParts[i]);
            sb.Append(args[i]?.ToString() ?? "");
        }
        sb.Append(_contentParts[_tagCount]);
        return sb.ToString();
    }

    // 直接存檔
    public void SaveAs(string file, Encoding encoding, Hashtable values)
    {
        File.WriteAllText(file, Render(values), encoding);
    }
    public void SaveAs(string file, Encoding encoding, params object[] args)
    {
        File.WriteAllText(file, Render(args), encoding);
    }
}

使用範例

基本渲染


var tpl = new TextTemplate("{alt}");

// 依順序
string html1 = tpl.Render("pic.jpg", "產品圖"); 

// 依名稱
var ht = new Hashtable { ["src"] = "pic.jpg", ["alt"] = "產品圖" };
string html2 = tpl.Render(ht);

生成 Web.config (安裝精靈常用)


// 模板檔 Web.config.template
/*
<connectionStrings>
  <add name="MainDb" connectionString="{CONN_STR}" providerName="System.Data.SqlClient" />
</connectionStrings>
*/

var cfgTpl = new TextTemplate("Web.config.template", Encoding.UTF8);
cfgTpl.SaveAs("Web.config", Encoding.UTF8, 
    new Hashtable { ["CONN_STR"] = "Server=.;Database=MyDb;Integrated Security=True" });

比起 XmlDocument 操作節點,模板法更直觀、易維護、支援任意文字格式 (HTML、XML、JSON、SQL、CodeGen)。

進階功能:模板分割 Split

支援以特定標記為界,將大模板拆分為多個子模板 (如分段生成頁首/內容/頁尾)。

效能優勢分析

指標String.Replace 迴圈TextTemplate
模板解析次數每次渲染都解析僅初始化一次
字串配置每次 Replace 產生新字串單次 StringBuilder 組裝
標記值含標記風險高 (巢狀替換錯誤)無 (不遞迴替換)
適用場景極簡單、單次渲染高頻、大模板、多頁生成

總結

TextTemplate 展示了「預編譯模板」的經典模式,程式碼精簡無相依,適合嵌入專案作為輕量靜態頁生成、程式碼產生、設定檔模板化的基礎設施。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved