Open kobynz opened 4 years ago
Another update on this, It seems my "weakly typed" version of this function is able to render my template just fine.
My template still has @inherits RazorEngineCore.RazorEngineTemplateBase<MyModelType>
private static ConcurrentDictionary<int, IRazorEngineCompiledTemplate> TemplateCache =
new ConcurrentDictionary<int, IRazorEngineCompiledTemplate>();
public static string Render(string template, object model, Assembly[] referencedAssemblies = null)
{
int templateHashCode = template.GetHashCode();
var compiledTemplate = TemplateCache.GetOrAdd(templateHashCode, i =>
{
var razorEngine = new RazorEngine();
return razorEngine.Compile(template, builder =>
{
if (referencedAssemblies != null)
{
foreach (var assembly in referencedAssemblies)
{
builder.AddAssemblyReference(assembly);
}
}
});
});
return compiledTemplate.Run(model);
}
I'm guessing the null issue is related to using the generic Compile<T>
.
Its because of new
keywork I used: https://github.com/adoconnection/RazorEngineCore/blob/master/RazorEngineCore/RazorEngineTemplateBaseT.cs
Thats design issue, I need to think a little.
as a quick solution I would simplify cache dictionary:
private static ConcurrentDictionary<int, object> TemplateCache = new ConcurrentDictionary<int, object>();
public static string Render<TModel>(string template, TModel model, Assembly[] referencedAssemblies = null)
{
int templateHashCode = template.GetHashCode();
var compiledTemplate = (IRazorEngineCompiledTemplate<RazorEngineTemplateBase<TModel>>) TemplateCache.GetOrAdd(templateHashCode, i =>
{
var razorEngine = new RazorEngine();
var compiledTemplate = razorEngine.Compile<RazorEngineTemplateBase<TModel>>(template, builder =>
{
});
return compiledTemplate;
});
return compiledTemplate.Run(instance =>
{
instance.Model = model;
});
}
This is a design expression issue I've long struggled with in C#.
C# 9 will supposedly be implementing covariant overrides. That would solve this issue, but is a ways out https://github.com/dotnet/csharplang/issues/2844
Maybe not so far out. Looks like they plan to release C# 9 with .NET 5, which is already to release candidates https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version
Cool, however this breaking change for new
keywork is confusing.
I would prefer something like this, with override
keyword
public abstract class RazorEngineTemplateBase<T> : RazorEngineTemplateBase
{
public override T Model { get; set; }
}
public abstract class RazorEngineTemplateBase : IRazorEngineTemplate
{
public virtual dynamic Model { get; set; }
}
That appears to be the design they're going for. https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/covariant-returns.md#motivation
I wasn't clear that this library would need to change from new to override.
good news anyway :)
I've run into an issue when attempting to strongly type a template. My template has
@inherits RazorEngineCore.RazorEngineTemplateBase<MyModelType>
at the top, and this makes intellisense work nicely.The template compiles just fine, but when I run it, I always get "Object not sent to instance of an object" when I reference any property on my model. I know my model is not null. It works fine when render it without using
RazorEngineTemplateBase
.Running a template with
@(Model == null)
works, but always renders "True".My generic render function:
Any help on this would be greatly appreciated. Thanks.