Как создаются шаблоны в 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
, который загружает кешированный контент с диска.