using System.Collections.Generic; using HandlebarsDotNet; using Open.Threading; namespace MfGames.Nitride.Handlebars; /// /// Implements a cache for templates to prevent compiling the same template /// more than once. /// public class HandlebarsTemplateCache { private readonly IHandlebars handlebars; private readonly ModificationSynchronizer locker; private readonly Dictionary> templates; public HandlebarsTemplateCache(IHandlebars handlebars) { this.handlebars = handlebars; this.locker = new ModificationSynchronizer(); this.templates = new Dictionary>(); } /// /// Caches the template by name based on the contents of the disk. It /// does it once in a multi-threaded manner to ensure it is only cached /// once in memory. /// /// The string that contains the template. /// public HandlebarsTemplate GetLiteralTemplate(string literal) { // Start with a read lock to see if we've already compiled it. this.locker.Modifying( () => !this.templates.ContainsKey(literal), () => { HandlebarsTemplate template = this.handlebars!.Compile(literal); this.templates[literal] = template; return true; }); return this.locker.Reading(() => this.templates[literal]); } /// /// Caches the template by name based on the contents of the disk. It /// does it once in a multi-threaded manner to ensure it is only cached /// once in memory. /// /// /// public HandlebarsTemplate GetNamedTemplate(string templateName) { string template = $"{{{{> {templateName}}}}}"; return this.GetLiteralTemplate(template); } }