Scriban - 列出已解析的表达式(变量)
Scriban - list parsed expressions (variables)
我想知道如何使用简单的代码片段列出所有已解析的表达式(变量):
var template = Template.Parse(@"
<ul id='products'>
{{ for product in products }}
<li>
<h2>{{ product.name }}</h2>
Price: {{ product.price }}
{{ product.description | string.truncate 15 }}
</li>
{{ end }}
</ul>
");
我需要知道使用的变量,以便只获取我真正需要的数据(数据库数据)。是否有一些内置方法或我需要实现自己的方法?
看起来您可以在计算期间使用自定义 TemplateContext
访问表达式树。但这要求模板中的所有全局变量(products
此处)都在上下文中注册,至少以虚拟形式注册。
例如:
class ScriptVariableMemberExpressionVisitorTemplateContext : TemplateContext
{
private readonly Action<ScriptVariableGlobal, ScriptVariableGlobal> memberExpressionVisitor;
public ScriptVariableMemberExpressionVisitorTemplateContext(
Action<ScriptVariableGlobal, ScriptVariableGlobal> memberExpressionVisitor)
{
this.memberExpressionVisitor = memberExpressionVisitor ??
throw new ArgumentNullException(nameof(memberExpressionVisitor));
}
protected override object EvaluateImpl(ScriptNode scriptNode)
{
var memberExpression = scriptNode as Scriban.Syntax.ScriptMemberExpression;
if (memberExpression != null
&& memberExpression.Target is ScriptVariableGlobal
&& memberExpression.Member is ScriptVariableGlobal)
{
this.memberExpressionVisitor((ScriptVariableGlobal)memberExpression.Target, (ScriptVariableGlobal)memberExpression.Member);
}
return base.EvaluateImpl(scriptNode);
}
}
...
var template = Template.Parse(@"
<ul id='products'>
{{ for product in products }}
<li>
<h2>{{ product.name }}</h2>
Price: {{ product.price }}
{{ product.description | string.truncate 15 }}
</li>
{{ end }}
</ul>
");
Dictionary<string, HashSet<string>> productFields = new Dictionary<string, HashSet<string>>();
var context = new ScriptVariableMemberExpressionVisitorTemplateContext(
(target, member) =>
{
if (!productFields.ContainsKey(target.Name))
{
productFields[target.Name] = new HashSet<string>();
}
productFields[target.Name].Add(member.Name);
});
var scriptObject = new ScriptObject();
scriptObject.Import(new { products = new[] { new { } } }); //required: `products` object from the template
context.PushGlobal(scriptObject);
template.Evaluate(context);
productFields["product"].ToList().ForEach(Console.WriteLine); //show fields from product object, used by the template
输出是模板中的字段列表:
name
price
description
我想知道如何使用简单的代码片段列出所有已解析的表达式(变量):
var template = Template.Parse(@"
<ul id='products'>
{{ for product in products }}
<li>
<h2>{{ product.name }}</h2>
Price: {{ product.price }}
{{ product.description | string.truncate 15 }}
</li>
{{ end }}
</ul>
");
我需要知道使用的变量,以便只获取我真正需要的数据(数据库数据)。是否有一些内置方法或我需要实现自己的方法?
看起来您可以在计算期间使用自定义 TemplateContext
访问表达式树。但这要求模板中的所有全局变量(products
此处)都在上下文中注册,至少以虚拟形式注册。
例如:
class ScriptVariableMemberExpressionVisitorTemplateContext : TemplateContext
{
private readonly Action<ScriptVariableGlobal, ScriptVariableGlobal> memberExpressionVisitor;
public ScriptVariableMemberExpressionVisitorTemplateContext(
Action<ScriptVariableGlobal, ScriptVariableGlobal> memberExpressionVisitor)
{
this.memberExpressionVisitor = memberExpressionVisitor ??
throw new ArgumentNullException(nameof(memberExpressionVisitor));
}
protected override object EvaluateImpl(ScriptNode scriptNode)
{
var memberExpression = scriptNode as Scriban.Syntax.ScriptMemberExpression;
if (memberExpression != null
&& memberExpression.Target is ScriptVariableGlobal
&& memberExpression.Member is ScriptVariableGlobal)
{
this.memberExpressionVisitor((ScriptVariableGlobal)memberExpression.Target, (ScriptVariableGlobal)memberExpression.Member);
}
return base.EvaluateImpl(scriptNode);
}
}
...
var template = Template.Parse(@"
<ul id='products'>
{{ for product in products }}
<li>
<h2>{{ product.name }}</h2>
Price: {{ product.price }}
{{ product.description | string.truncate 15 }}
</li>
{{ end }}
</ul>
");
Dictionary<string, HashSet<string>> productFields = new Dictionary<string, HashSet<string>>();
var context = new ScriptVariableMemberExpressionVisitorTemplateContext(
(target, member) =>
{
if (!productFields.ContainsKey(target.Name))
{
productFields[target.Name] = new HashSet<string>();
}
productFields[target.Name].Add(member.Name);
});
var scriptObject = new ScriptObject();
scriptObject.Import(new { products = new[] { new { } } }); //required: `products` object from the template
context.PushGlobal(scriptObject);
template.Evaluate(context);
productFields["product"].ToList().ForEach(Console.WriteLine); //show fields from product object, used by the template
输出是模板中的字段列表:
name
price
description