Scriban - список проанализированных выражений (переменных) - PullRequest
1 голос
/ 07 ноября 2019

Мне интересно, как составить список всех проанализированных выражений (переменных) с помощью простого фрагмента кода:

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

Мне нужно знать используемые переменные в orde для выборки только данных (данных БД) Iочень нужно. Есть какой-то встроенный метод или мне нужно реализовать свой собственный?

1 Ответ

1 голос
/ 07 ноября 2019

Похоже, вы можете использовать пользовательский 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
...