internal CompiledTemplate([NotNull] TemplateDocument document, [NotNull] CompiledEvaluationDelegate <TContext> evaluationDelegate) { Debug.Assert(document != null, "Argument document cannot be null."); Debug.Assert(evaluationDelegate != null, "Argument evaluationDelegate cannot be null."); _document = document; _evaluationDelegate = evaluationDelegate; }
/// <summary> /// Constructs a delegate used in evaluation of a given double-tag <paramref name="directive"/>. /// </summary> /// <remarks> /// <see cref="BuildDoubleTagDirectiveEvaluationDelegate"/> method is used to build a new delegate for directives /// that are composed of two tags(e.g. <c>{IF}...{END}</c>. The contents (all inner document nodes) found between the directive's tags is /// passed along in <paramref name="innerDelegate"/> parameter. If there are no nodes between its two consecutive tags, a <c>null</c> value /// is passed. The <paramref name="openComponents"/> and <paramref name="closeComponents"/> contain the components for the opening and closing tags. /// </remarks> /// <param name="directive">The directive.</param> /// <param name="innerDelegate">A delegate that represents the contents of the inner nodes.</param> /// <param name="openComponents">The components associated with the opening tag.</param> /// <param name="closeComponents">The components associated with the closing tag.</param> /// <returns>A new delegate tasked with evaluating the given directive.</returns> protected override CompiledEvaluationDelegate <EvaluationContext> BuildDoubleTagDirectiveEvaluationDelegate( Directive directive, CompiledEvaluationDelegate <EvaluationContext> innerDelegate, object[] openComponents, object[] closeComponents) { Debug.Assert(directive != null, "Argument directive cannot be null."); Debug.Assert(openComponents != null, "Argument openComponents cannot be null."); Debug.Assert(openComponents.Length > 0, "Argument openComponents cannot be empty."); Debug.Assert(closeComponents != null, "Argument closeComponents cannot be null."); Debug.Assert(closeComponents.Length > 0, "Argument closeComponents cannot be empty."); return((writer, context) => { context.OpenEvaluationFrame(); try { EvaluateDoubleTagDirective( writer, context, directive, openComponents, closeComponents, innerDelegate); } catch (OperationCanceledException) { throw; } catch (Exception exception) { if (!context.IgnoreEvaluationExceptions) { ExceptionHelper.DirectiveEvaluationError(exception, directive); } } finally { context.CloseEvaluationFrame(); } }); }
protected abstract CompiledEvaluationDelegate <TContext> BuildDoubleTagDirectiveEvaluationDelegate( [NotNull] Directive directive, [NotNull] CompiledEvaluationDelegate <TContext> innerDelegate, [NotNull] object[] openComponents, [NotNull] object[] closeComponents);
private static void EvaluateDoubleTagDirective( [NotNull] TextWriter writer, [NotNull] EvaluationContext context, [NotNull] Directive directive, [NotNull] IReadOnlyList <object> beginComponents, [NotNull] IReadOnlyList <object> closeComponents, [CanBeNull] CompiledEvaluationDelegate <EvaluationContext> beginToCloseEvaluateProc) { /* Get tag components. */ var beginTagEvaluatedComponents = EvaluateTag(context, beginComponents); object[] closeTagEvaluatedComponents = null; /* Evaluate tag. */ object state = null; while (true) { /* Check for cancellation. */ context.CancellationToken.ThrowIfCancellationRequested(); var flowDecision = directive.Execute(0, beginTagEvaluatedComponents, ref state, context, out string directiveText); /* Check for cancellation. */ context.CancellationToken.ThrowIfCancellationRequested(); if (directiveText != null) { writer.Write(directiveText); } if (flowDecision == Directive.FlowDecision.Terminate) { break; } switch (flowDecision) { case Directive.FlowDecision.Restart: continue; case Directive.FlowDecision.Evaluate: beginToCloseEvaluateProc?.Invoke(writer, context); break; case Directive.FlowDecision.Terminate: break; case Directive.FlowDecision.Skip: break; default: throw new ArgumentOutOfRangeException(nameof(flowDecision)); } if (closeTagEvaluatedComponents == null) { closeTagEvaluatedComponents = EvaluateTag(context, closeComponents); } /* Check for cancellation. */ context.CancellationToken.ThrowIfCancellationRequested(); flowDecision = directive.Execute(1, closeTagEvaluatedComponents, ref state, context, out directiveText); if (directiveText != null) { writer.Write(directiveText); } if (flowDecision == Directive.FlowDecision.Terminate) { break; } } }