我刚写了一个简单的类。它只需要一串输入,如
您好 @name ,今天你看 @adjective !
并用字典中的值替换@variables
。例如,传入new Dictionary<string,object>{{"name","Ralph"},{"adjective","stunning"}}
会给出:
拉尔夫你好,今天你看起来很棒!
这是班级:
class Template
{
List<object> nodes = new List<object>();
public Template(string content)
{
for (int i = 0; i < content.Length; ++i)
{
char ch = content[i];
if (ch == '@')
{
var match = Regex.Match(content.Substring(i + 1), @"\w+");
if (match.Success)
{
nodes.Add(new Variable(match.Value));
i += match.Value.Length;
}
else
{
throw new Exception(string.Format("Expected variable name after @ symbol at character {0}", i));
}
}
else
{
nodes.Add(ch.ToString());
}
}
}
public string Render(Dictionary<string,object> dict)
{
var sb = new StringBuilder();
foreach (var item in nodes)
{
if (item is Variable)
{
sb.Append(dict[((Variable)item).Name]);
}
else
{
sb.Append(item);
}
}
return sb.ToString();
}
class Variable
{
public readonly string Name;
public Variable(string name)
{
Name = name;
}
}
}
这是解决这个问题的好方法吗?我想在构造函数中尽可能多地进行处理,以便我可以有效地重复渲染模板而无需重新分析它。
现在我循环遍历整个节点列表,寻找变量节点,以便我可以替换它们。也许有一种方法可以“跳过”这些节点?那会有帮助吗?
另外,我正在逐个字符地解析它,但后来我使用正则表达式(我想从下一个字符开始,所以我使用.Substring来获取字符串的其余部分)来获得“块”的文字。我不确定如何使用正则表达式获取整个变量名称?
这门课程要复杂得多,所以我想在进一步学习之前确保我有正确的方法。
我关注的是:
答案 0 :(得分:2)
怎么样:
s = s.Replace("@name", name);
s = s.Replace("@Adjective", adjective);
另外,我会避免在解析文本时抛出异常。由于用户字符串几乎可以包含任何内容,因此最好尽可能智能地尝试处理意外数据。
答案 1 :(得分:1)
您几乎肯定希望为节点使用某种关联容器,我是否可以推荐使用Dictionary<string, Node>
而不是List
?此外,我认为目前无法设置这些节点。而且你也可以继续将节点作为一个类,同时你就可以了。
至于使用char解析char然后使用正则表达式,是的,这可能并不理想,但编写tokenizer / lexer也不是最简单的任务。需要时修复它!
答案 2 :(得分:1)
如果您要多次使用该模板,我建议分两步解析模板,首先将文本分割为文字文本和字段对象,然后将它们存储在列表中,然后每次需要渲染它只需循环遍历列表并直接输出任何文字文本,并通过字典调用每个字段。
我们使用我们自己的temlpate引擎做了类似的事情,从正则表达式替换到预解析列表,并且性能提高了大约20倍:D。
您当前的代码非常适合拆分原始字符串。
示例:
List<Node> nodes = var list = new List<node> {new node {Type=ntypes.literal,Value="Hello "}, new node{Type=ntypes.field,Value="Name"}};
Enum NodeType {
field,
literal
}
class Node {
public enum NodeType;
public string Value;
}
如果您只使用它,您仍然可以拆分它,但是然后将数组保存为eaxmple JSON或序列化它,以便您可以非常轻松地重新创建列表而无需使用正则表达式。
如果数组包含带有(type,value)的元素,你可以随着时间的推移添加更多的智能,多个不同的字典或者像@@ substring(@field,10)那样的简单函数然后被解析和执行;)
但是对于更复杂的情况,寻求真正的解析器解决方案会更好,因为随着复杂性的增加,所有简单的解决方案都会变得笨拙而牺牲性能。
我们最终转向基于Antlr的解析器,目前正在查看渲染阶段的表达式树。
答案 3 :(得分:0)
不是循环遍历字符串的每个字符,而应该只对整个字符串执行RegEx并返回一组Matches。