2

我想知道如何使用一个简单的代码片段列出所有已解析的表达式(变量):

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>
");

我需要知道使用的变量才能只获取我真正需要的数据(数据库数据)。是否有一些内置方法或者我需要实现自己的方法?

4

1 回答 1

2

看起来您可以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
于 2019-11-07T17:05:30.767 回答