我应该采用哪种C#模板方法?

时间:2011-11-06 02:25:28

标签: c# regex templates

我有什么 我有存储在数据库中的模板,以及在C#中转换为字典的JSON数据。

示例:

模板:“嗨{FirstName}”

数据:“{FirstName:'Jack'}”

通过使用正则表达式提取模板中{}内的任何内容,可以轻松处理一级数据。

我想要什么 我希望能够更深入地了解JSON而不是第一层。

示例:

模板:“嗨{姓名:{First}}”

数据:“{Name:{First:'Jack',Last:'Smith'}}”

我应该采取什么方法? (以及从哪个选择开始的一些指导)

  1. 正则表达式
  2. 不在模板中使用JSON(支持xslt或类似的东西)
  3. 其他东西
  4. 我也希望能够遍历模板中的数据,但我根本不知道从哪一个开始!

    谢谢堆

4 个答案:

答案 0 :(得分:4)

你很幸运! SmartFormat完全按照您的描述完成。它是一个轻量级的开源字符串格式化实用程序。

它支持命名占位符

var template = " {Name:{Last}, {First}} ";

var data = new { Name = new { First="Dwight", Last="Schrute" } };

var result = Smart.Format(template, data);
// Outputs: " Schrute, Dwight " SURPRISE!

它还支持列表格式

var template = " {People:{}|, |, and} ";

var data = new { People = new[]{ "Dwight", "Michael", "Jim", "Pam" } };

var result = Smart.Format(template, data);
// Outputs: " Dwight, Michael, Jim, and Pam "

您可以查看Named PlaceholdersList Formatter的单元测试,以查看更多示例!

它甚至有几种形式的错误处理(忽略错误,输出错误,抛出错误)。

注意:命名占位符功能使用反射和/或字典查找,因此您可以将JSON反序列化为C#对象或嵌套Dictionaries,并且它可以正常工作!

答案 1 :(得分:2)

您是否考虑过使用Javascript作为脚本语言?虽然启动成本很高,但Jint取得了巨大的成功。另一种选择是Jurassic,我自己没有用过。

如果你碰巧有一个Web应用程序,使用Razor可能是一个想法,see here

使用Regex或任何类型的字符串解析当然可以解决琐碎的事情,但是当你想要逻辑甚至只是基本的层次结构时会很痛苦。如果将JSON反序列化为嵌套字典,则可以相对容易地构建解析器:

// Untested and error prone, just to illustrate the concept
var parts = "parentObj.childObj.property".split('.');
Dictionary<object,object> current = yourDeserializedObject;
foreach(var key in parts.Take(parts.Length-1)){
    current = current[key];
}
var value = current[parts.Last()];

无论你做什么,都不要做XSLT。真的,如果XSLT是答案那么问题肯定是非常绝望的:)

答案 2 :(得分:2)

我将如何做到这一点:

将模板更改为此格式Hi {Name.First}

现在创建一个JavaScriptSerializer来转换Dictionary<string, object>

中的JSON
JavaScriptSerializer jss = new JavaScriptSerializer();
dynamic d = jss.Deserialize(data, typeof(object));

现在,变量d在字典中包含JSON的值。

有了这个,您可以针对正则表达式运行模板,以递归方式将{X.Y.Z.N}替换为字典的键。

完整示例:

public void Test()
{
    // Your template is simpler
    string template = "Hi {Name.First}";

    // some JSON
    string data = @"{""Name"":{""First"":""Jack"",""Last"":""Smith""}}";

    JavaScriptSerializer jss = new JavaScriptSerializer();

    // now `d` contains all the values you need, in a dictionary
    dynamic d = jss.Deserialize(data, typeof(object));

    // running your template against a regex to
    // extract the tokens that need to be replaced
    var result = Regex.Replace(template, @"{?{([^}]+)}?}", (m) =>
        {
            // Skip escape values (ex: {{escaped value}} )
            if (m.Value.StartsWith("{{"))
                return m.Value;

            // split the token by `.` to run against the dictionary
            var pieces = m.Groups[1].Value.Split('.');
            dynamic value = d;

            // go after all the pieces, recursively going inside
            // ex: "Name.First"

            // Step 1 (value = value["Name"])
            //    value = new Dictionary<string, object>
            //    {
            //        { "First": "Jack" }, { "Last": "Smith" }
            //    };

            // Step 2 (value = value["First"])
            //    value = "Jack"

            foreach (var piece in pieces)
            {
                value = value[piece]; // go inside each time
            }

            return value;
        });
}

我没有处理异常(例如找不到该值),您可以处理这种情况并返回匹配的值(如果找不到)。原始值为m.Valuem.Groups[1].Value之间的字符串为{}

答案 3 :(得分:1)

为什么不是我们nvelocity或其他什么?