- Notifications
You must be signed in to change notification settings - Fork 101
@Include and @Layout
Alexander edited this page Jul 1, 2020
·
6 revisions
Maintainer strongly believes implementing @include and @Layout is unnecessary complexity for standalone RazorEngine.
Since RazorEngine.Compile accept template as a string, one will need also to accept a
Dictionary (key, template)to be able to resolve@Includeand@LayoutIt is easily implementable outside of RazorEngine
We would like to have code like this:
Supply primary template, parts, and model and see the result as a string
namespaceConsoleApp11{classProgram{staticvoidMain(string[]args){stringtemplate=@" @{ Layout = ""MyLayout""; } <h1>@Model.Title</h1> @Include(""outer"", Model) ";IDictionary<string,string>parts=newDictionary<string,string>(){{"MyLayout",@" LAYOUT HEADER @RenderBody() LAYOUT FOOTER "},{"outer","This is Outer include, <@Model.Title>, @Include(\"inner\")"},{"inner","This is Inner include"}};IRazorEnginerazorEngine=newRazorEngine();MyCompiledTemplatecompiledTemplate=razorEngine.Compile(template,parts);stringresult=compiledTemplate.Run(new{Title="Hello"});Console.WriteLine(result);Console.ReadKey();}}}Output
LAYOUT HEADER
<h1>Hello</h1>
This is Outer include, <Hello>, This is Inner include
LAYOUT FOOTERLets make custom template base with Include function. It will be available as @Include("footer") in template. We will inialize IncludeCallback just before running template
publicclassMyTemplateBase:RazorEngineTemplateBase{publicFunc<string,object,string>IncludeCallback{get;set;}publicFunc<string>RenderBodyCallback{get;set;}publicstringLayout{get;set;}publicstringInclude(stringkey,objectmodel=null){returnthis.IncludeCallback(key,model);}publicstringRenderBody(){returnthis.RenderBodyCallback();}}publicstaticclassRazorEngineCoreExtensions{publicstaticMyCompiledTemplateCompile(thisRazorEnginerazorEngine,stringtemplate,IDictionary<string,string>parts){returnnewMyCompiledTemplate(razorEngine.Compile<MyTemplateBase>(template),parts.ToDictionary(
k =>k.Key,
v =>razorEngine.Compile<MyTemplateBase>(v.Value)));}}publicclassMyCompiledTemplate{privatereadonlyIRazorEngineCompiledTemplate<MyTemplateBase>compiledTemplate;privatereadonlyDictionary<string,IRazorEngineCompiledTemplate<MyTemplateBase>>compiledParts;publicMyCompiledTemplate(IRazorEngineCompiledTemplate<MyTemplateBase>compiledTemplate,Dictionary<string,IRazorEngineCompiledTemplate<MyTemplateBase>>compiledParts){this.compiledTemplate=compiledTemplate;this.compiledParts=compiledParts;}publicstringRun(objectmodel){returnthis.Run(this.compiledTemplate,model);}publicstringRun(IRazorEngineCompiledTemplate<MyTemplateBase>template,objectmodel){MyTemplateBasetemplateReference=null;stringresult=template.Run(instance =>{if(!(modelisAnonymousTypeWrapper)){model=newAnonymousTypeWrapper(model);}instance.Model=model;instance.IncludeCallback=(key,includeModel)=>this.Run(this.compiledParts[key],includeModel);templateReference=instance;});if(templateReference.Layout==null){returnresult;}returnthis.compiledParts[templateReference.Layout].Run(instance =>{if(!(modelisAnonymousTypeWrapper)){model=newAnonymousTypeWrapper(model);}instance.Model=model;instance.IncludeCallback=(key,includeModel)=>this.Run(this.compiledParts[key],includeModel);instance.RenderBodyCallback=()=>result;});}publicvoidSave(){/* TODO this.compiledTemplate.SaveToFile(); this.compiledTemplate.SaveToStream(); foreach (var compiledPart in this.compiledParts) { compiledPart.Value.SaveToFile(); compiledPart.Value.SaveToStream(); } */}publicvoidLoad(){// TODO}}