2010年10月12日 星期二

利用 Regex.Replace 的 MatchEvaluator 委派進行樣板字串置換

Regular Expression 真的很讚!尤其是在 .NET 中使用 Regex 物件時,你會感覺到非常幸福,不光是支援的中介符號和語法完整 (比較過 Javascript 的 Regular Expression 就知道),連 Regex.Replace 都有特別犀利的地方。

我們在程式寫作的時候的時候,偶爾會遇到需要處理樣板的情況,例如:

Hi! XXX您好,您月的贍養管理費未繳,請盡速繳納...

作為程式設計師,你一定有很多種方法完成這項工作,可能直接用 string 去加出來,也可能用 StringBuilder 做。當然囉!這邊要展示的就是利用 Regex.Replace,參考的程式碼如下:

class Program
{
    static void Main(string[] args)
    {
        string template, result;

        // 匿名物件
        template = "Hi! [Name]您好,您[Month]月的管理費未繳,請盡速繳納...";
        var userObject = new { Name = "Nobody", Month = "五" };
        result = template.TemplateSubstitute(userObject);
        Console.WriteLine(result);   //Hi! Nobody您好,您五月的管理費未繳,請盡速繳納...

        // 使用任意物件(讀取屬性並置換)
        template = "今天是西元[Year]年[Month]月[Day]日";
        result = template.TemplateSubstitute(DateTime.Now);
        Console.WriteLine(result);   //今天是西元2010年10月12日
    }
}

public static class StringExtension
{
    public static string TemplateSubstitute(this string input, object data)
    {
        var type = data.GetType();
        return Regex.Replace(input, @"\[(\w+)\]", m =>
        {
            var name = m.Groups[1].Value;
            var prop = type.GetProperty(name);
            if (prop != null)
            {
                // 找到屬性,傳回屬性值執行字串替換
                return prop.GetValue(data, null).ToString();
            }
            else
            {
                // 在物件中找不到符合名稱的屬性,回傳原值不處理
                return m.Value;
            }
        });
    }
}

範例中使用 Extension method 擴充 String 提供一個 TemplateSubstitute 方法,在這個方法中利用 Regex.Replace 尋找符合樣板規格的 [ ] 區塊,並提供一個 lambda 給 Regex.Replace 作為回呼(Callback),重要的是使用這個方法不需要自行處理字串的組合,或是多次呼叫 Regex.Replace 取得最後的結果,而只要在 lambda 中回傳我要替代的內容就可以囉,很棒吧!

參考資料

沒有留言: