Как создаются шаблоны в RazorEngine?

Когда вы вызываете RazorEngine.Razor.Compile(), где хранится скомпилированный шаблон?

Доступен ли он после перезапуска программ? Если есть нехватка памяти, она будет сброшена?

Я использую RazorEngine в ASP.NET (MVC). Будут ли предварительно скомпилированные шаблоны доступны после перезапуска приложения?

Будет ли у меня больше смысла хранить их в HttpContext.Cache? Если бы я это сделал, тогда было бы разумнее использовать другую функцию (отличную от Compile), которая обходит внутренний кеш? Есть ли способ выполнить ITemplate и просто передать ему модель?

Выполняет ли RazorEngine.Razor.Parse() кэширование? Или шаблон перекомпилирован каждый раз?

Ответ 1

В настоящее время после того, как RazorEngine скомпилирует шаблоны, они загружаются в память. Эти сборки сохраняются только в памяти и не выходят за пределы срока службы приложения.

Я рассматриваю возможность добавления поддержки для сборки этих сборок в файлы, но это будет будущая версия.

Если вы вызываете Razor.Parse и передаете имя для шаблона, оно будет пытаться

  • Проверьте кеш сборок в памяти для сборки с тем же именем.
  • Неверный кеш содержимого шаблона изменился.
  • Кэш недавно скомпилированного шаблона.

Ответ 2

У меня есть это для работы с RazorEngine 3.4.1.0, установленным в конце января 2014 года.

Ключом является вызов дорогостоящего Razor.Compile(content, name) для размещения шаблона в кеше, а затем вызов дешевого Razor.Run(name, model) для выполнения шаблона.

Помните, что чтение содержимого шаблона может быть дорогостоящим - скажем, с использованием чтения с диска - поэтому мое решение получает только контент шаблона один раз. Это может быть слишком много кэширования для вас, так осторожно!

Здесь метод RenderPartial, который я использую внутри пользовательского подкласса TemplateBase<T>. Он работает очень быстро для нескольких вызовов одного и того же шаблона.

public abstract class SqlTemplate<T>: TemplateBase<T>
{
    public string RenderPartial(string templateName, object model = null)
    {
        // loading a template might be expensive, so be careful to cache content
        if (Razor.Resolve(templateName) == null)
        {
            // we've never seen this template before, so compile it and stick it in cache.
            var templateContent = GetTemplateContent(templateName);
            Razor.Compile(templateContent, templateName);
        }

        // by now, we know we've got a the template cached and ready to run; this is fast
        var renderedContent = Razor.Run(templateName, model); 
        return renderedContent;
    }

    private string GetTemplateContent(string templateName)
    {
        ... your implementation here
    }
}

Вам также нужно указать Razor использовать этот базовый класс (SqlTempalte<T>), который вы можете сделать так, вызывая RazorEngineConfigurator.Configure();

public static class RazorEngineConfigurator
{
    private static bool configured = false;

    public static void Configure()
    {
        if (configured) 
        {
            return;
        }

        var templateConfig = new TemplateServiceConfiguration
        {
            BaseTemplateType = typeof(SqlTemplate<>), 
            EncodedStringFactory = new RazorEngine.Text.RawStringFactory()
        };

        RazorEngine.Razor.SetTemplateService(new TemplateService(templateConfig));

        configured = true;
    }
}

Не удалось сделать это без этого SO-ответа - почему бы не дать этому голосование тоже?:)


Изменить. Если вам нужно выполнить кеширование более подробно, вам понадобится использовать другой подход, используя RazorEngineTemplateService и ITemplateResolver.

Вот фрагмент кода стартера,

    public static RazorEngineTemplateService CreateService(ITemplateResolver resolver, ICollection<string> namespaces)
    {
        Check.IsNotNull(resolver, "resolver");
        var config = new TemplateServiceConfiguration();
        config.BaseTemplateType = typeof(PlainTextTemplate<>);
        config.EncodedStringFactory = new RazorEngine.Text.RawStringFactory();
        config.Resolver = resolver;
        config.Namespaces = new HashSet<string>(namespaces);

        var service = new RazorEngineTemplateService(config);
        return service;
    }

ITemplateResolver превращает имена шаблонов в содержимое шаблона, поэтому вы можете реализовать, например, CachedFileTemplateResolver, который загружает кешированный контент с диска.