.NET模板引擎中的字符串格式(理想情况下为Mustache)

时间:2014-04-24 20:52:58

标签: c# .net template-engine

我正在编写一个需要使用HTML文件作为模板的报告系统。我正在考虑使用Nustache来处理它,因为它看起来很理想且非常轻巧。我唯一的问题是我需要能够在数字数据绑定项中指定特定数量的小数位。

我知道我可以在datasource中有一个accessor属性,它在内部执行String.Format,然后返回一个表示该数字的格式化字符串。这个问题是模板本身不能指定格式(例如小数位数)。

有没有办法可以从模板本身指定小数位?因为我非常喜欢Nustache,所以我正在编写一些处理格式之前和之后处理模板文件的内容。但是想要检查一下,如果已经支持我,我就不会重新发明轮子,而我只是错过了一些现有的功能。

我想的是,在允许Nustache执行此操作之前,预处理是否将{{MyNumber|3}}替换为<$$${{MyNumber}}|3$$$>。其中3是小数位数。所以它看起来像<$$$123|3$$$>。然后在Nustache处理之后,我有一个后处理,它使用正则表达式提取Nustache插入的数字和3,然后做一个字符串格式并替换。请注意,<$$$$$$>只是由字符串组成,以指示后处理需要处理的块的开始和结束。

在我的情况下,我只需要这个来指定小数位,所以我可以安全地假设其中{{x | y}}的任何内容都是十进制值,其中y表示小数位数地方。

我是否正在重新发明轮子?还有其他想法吗?或者这个解决方案的问题?

1 个答案:

答案 0 :(得分:0)

我实际上已经实施了我的建议,因为它没有花太多时间去做。似乎很好地工作。它是有限的,因为它假设{{x|y}}是x作为十进制类型而y是十进制字符数。我还使用了<######>,因为正则表达式替换字符串中使用了$(例如,$ 1是第一个匹配的组等)。所以使用#意味着我没有逃脱它们。

只是感兴趣的人,这里有代码:

using System.Text.RegularExpressions;

public static class NustacheUtil
{
    public static string PreProcess(string templateString)
    {
        return Regex.Replace(templateString, @"{{(.*?)\|(\d+)}}", @"<###{{$1}}|$2###>");
    }

    public static string PostProcess(string templateString)
    {
        var result = templateString;

        for(;;)
        {
            var match = Regex.Match(result, @"<###([0-9.]+?)\|(\d+)###>");

            if(!match.Success || match.Groups.Count != 3)
            {
                break;
            }

            decimal value;

            if(decimal.TryParse(match.Groups[1].Value, out value))
            {
                var numDecimalPlaces = match.Groups[2].Value;
                result = result.Remove(match.Index, match.Length);
                result = result.Insert(match.Index, value.ToString("N" + numDecimalPlaces));
            }
        }

        return result;
    }
}

还有一些测试:

using NUnit.Framework;

[TestFixture]
class NustacheUtilTests
{
    [Test]
    public void PreProcessTest_Single()
    {
        // Arrange
        const string templateString = "Test number: {{MyNumber|3}}";

        // Act
        var result = NustacheUtil.PreProcess(templateString);

        // Assert
        Assert.That(result, Is.EqualTo("Test number: <###{{MyNumber}}|3###>"));
    }

    [Test]
    public void PostProcessTest_Single()
    {
        // Arrange
        const string templateString = "Test number: <###123.456789|3###>";

        // Act
        var result = NustacheUtil.PostProcess(templateString);

        // Assert
        Assert.That(result, Is.EqualTo("Test number: 123.457"));
    }

    [Test]
    public void PreProcessTest_Multiple()
    {
        // Arrange
        const string templateString = "Test number: {{MyNumber|3}}, and another: {{OtherNumber|2}}";

        // Act
        var result = NustacheUtil.PreProcess(templateString);

        // Assert
        Assert.That(result, Is.EqualTo("Test number: <###{{MyNumber}}|3###>, and another: <###{{OtherNumber}}|2###>"));
    }

    [Test]
    public void PostProcessTest_Multiple()
    {
        // Arrange
        const string templateString = "Test number: <###123.457|3###>, and another: <###947.74933|2###>";

        // Act
        var result = NustacheUtil.PostProcess(templateString);

        // Assert
        Assert.That(result, Is.EqualTo("Test number: 123.457, and another: 947.75"));
    }
}

使用Nustache:

var templateString = NustacheUtil.PreProcess(templateString);
templateString = Render.StringToString(templateString, dataSource);
templateString = NustacheUtil.PostProcess(templateString);

它显然还没有被用于愤怒。我在进行更改时会在此处更新代码,因为我确信在正确使用它时我会做出改进。