/// <summary> /// Raises the <see cref="Include"/> event. /// </summary> /// <param name="e">The <see cref="TextTemplate.IncludeEventArgs"/> instance containing the event data.</param> protected virtual void OnInclude(IncludeEventArgs e) { if (Include != null) { Include(this, e); } }
/// <summary> /// Pre-processes the template code to handle include-directives. /// </summary> /// <param name="content"> /// The content to pre-process. /// </param> /// <param name="inclusionStack"> /// This structure is used to detect cycles in included content, where one included /// piece of content includes another, which again includes the first. /// </param> /// <returns> /// The preprocessed code. /// </returns> /// <exception cref="ArgumentNullException"> /// <para><paramref name="content"/> is <c>null</c>.</para> /// </exception> private string PreProcessCode(string content, HashSet <string> inclusionStack) { if (content == null) { throw new ArgumentNullException("content"); } var parser = new TemplateParser(content); parser.Parse(); var sb = new StringBuilder(); if (inclusionStack.Count == 0) { sb.AppendFormat("<%@ language {0} %>{1}", parser.Language, Environment.NewLine); } foreach (string reference in parser.AssemblyReferences) { sb.AppendFormat("<%@ references {0} %>{1}", reference, Environment.NewLine); } foreach (string import in parser.NamespaceImports) { sb.AppendFormat("<%@ using {0} %>{1}", import, Environment.NewLine); } foreach (string part in parser.CodeParts) { if (part.StartsWith("<%@", StringComparison.Ordinal)) { string subContent = part.Substring(3, part.Length - 5).Trim(); if (subContent.StartsWith("include ", StringComparison.OrdinalIgnoreCase)) { string name = subContent.Substring(7).Trim(); if (inclusionStack.Contains(name)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "A cycle is detected in included content, was triggered by {0}, stack already contains {1}", name, string.Join(", ", inclusionStack.ToArray()))); } var includeEventArgs = new IncludeEventArgs(name); OnInclude(includeEventArgs); if (!includeEventArgs.Handled) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to include content named '{0}'", name)); } inclusionStack.Add(name); sb.Append(PreProcessCode(includeEventArgs.Content, inclusionStack)); inclusionStack.Remove(name); } else { sb.Append(part); } } else { sb.Append(part); } } return(sb.ToString()); }