如何在字符串模板上替换标记?

时间:2013-12-18 07:11:05

标签: c# template-engine

我正在尝试学习编写基本的模板引擎实现。例如,我有一个字符串:

string originalString = "The current Date is: {{Date}}, the time is: {{Time}}";

读取每个{{}}的内容然后用有效字符串替换整个标记的最佳方法是什么?

编辑:感谢BrunoLM指出我正确的方向,到目前为止这是我所拥有的并且解析得很好,我还能做其他任何事情来优化这个功能吗?

private const string RegexIncludeBrackets = @"{{(.*?)}}";

public static string ParseString(string input)
{
    return Regex.Replace(input, RegexIncludeBrackets, match =>
    {
        string cleanedString = match.Value.Substring(2, match.Value.Length - 4).Replace(" ", String.Empty);
        switch (cleanedString)
        {
            case "Date":
                return DateTime.Now.ToString("yyyy/MM/d");
            case "Time":
                return DateTime.Now.ToString("HH:mm");
            case "DateTime":
                return DateTime.Now.ToString(CultureInfo.InvariantCulture);
            default:
                return match.Value;
        }
    });
}

1 个答案:

答案 0 :(得分:1)

简短回答

我认为最好使用正则表达式。

var result = Regex.Replace(str, @"{{(?<Name>[^}]+)}}", m =>
{
    return m.Groups["Name"].Value; // Date, Time
});

上,您可以使用:

string result = $"Time: {DateTime.Now}";

String.Format&amp; IFormattable

然而,已经有一种方法。 Documentation

String.Format("The current Date is: {0}, the time is: {1}", date, time);

此外,您可以使用IFormattable的课程。我没有进行性能测试,但这个可能很快:

public class YourClass : IFormattable
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (format == "Date")
            return DateTime.Now.ToString("yyyy/MM/d");
        if (format == "Time")
            return DateTime.Now.ToString("HH:mm");
        if (format == "DateTime")
            return DateTime.Now.ToString(CultureInfo.InvariantCulture);

        return format;

        // or throw new NotSupportedException();
    }
}

并用作

String.Format("The current Date is: {0:Date}, the time is: {0:Time}", yourClass);

审核您的代码和详细信息

在您当前的代码中使用

// match.Value = {{Date}}
match.Value.Substring(2, match.Value.Length - 4).Replace(" ", String.Empty);

相反,如果你查看我上面的代码,我就使用了模式

@"{{(?<Name>[^}]+)}}"

语法(?<SomeName>.*)表示这是named group, you can check the documentation here.

它允许您访问match.Groups["SomeName"].Value,这与该组的模式相同。所以它会匹配两次,返回“Date”然后“Time”,所以你不需要使用SubString

更新您的代码,它将是

private const string RegexIncludeBrackets = @"{{(?<Param>.*?)}}";

public static string ParseString(string input)
{
    return Regex.Replace(input, RegexIncludeBrackets, match =>
    {
        string cleanedString = match.Groups["Param"].Value.Replace(" ", String.Empty);
        switch (cleanedString)
        {
            case "Date":
                return DateTime.Now.ToString("yyyy/MM/d");
            case "Time":
                return DateTime.Now.ToString("HH:mm");
            case "DateTime":
                return DateTime.Now.ToString(CultureInfo.InvariantCulture);
            default:
                return match.Value;
        }
    });
}

要进一步改进,您可以使用静态编译的Regex字段:

private static Regex RegexTemplate = new Regex(@"{{(?<Param>.*?)}}", RegexOptions.Compiled);

然后用作

RegexTemplate.Replace(str, match => ...);