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