lundi 11 décembre 2017

dotLiquid - Generic classes incompatible with Template.RegisterSafeType?

Because dotLiquid does not support member-level attribute decoration, I've created a custom attribute for my project and I'm registering the types and properties at run-time using the Template.RegisterSafeType() method of drop registration.

In other words, instead of the LiquidType class attribute like this...

[LiquidType("MyExposedValue")]
public class MyClass
{
    public string MyExposedValue { get; set; }
    public string MyHiddenValue { get; set; }
}

... I use my own custom dual-level attribute like this:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)]
public class LiquidSafeAttribute : Attribute
{
}

[LiquidSafe]
public class MyClass
{
    [LiquidSafe]
    public string MyExposedValue { get; set; }
    // No [LiquidSafe] attribute on this property, therefore not exposed
    public string MyHiddenValue { get; set; }
}

Then on app startup, I reflect over the types in the assembly and pass the decorated properties into Template.RegisterSafeType:

foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
    if (type.GetCustomAttribute<LiquidSafeAttribute>() != null)
    {
        Template.RegisterSafeType(type, type.GetProperties()
                .Where(p => Attribute.IsDefined(p, typeof(LiquidSafeAttribute)))
                .Select(p => p.Name).ToArray()
            );
    }
}

This works fine for everything... except generics:

[LiquidSafe]
public class MyClass<T>
{
    [LiquidSafe]
    public T MyExposedValue { get; set; }
    public string MyHiddenValue { get; set; }
}

For example, if I try to render a MyClass<string>, I get an error:

Liquid syntax error: Object 'DotLiquidTest.MyClass`1[System.String]' is invalid because it is neither a built-in type nor implements ILiquidizable

However, I've found that if I create a new class that inherits from MyClass<string>, it works fine:

[LiquidSafe]
public class MyStringClass : MyClass<string>
{
}

Here's the .NET fiddle demonstrating the working implementation with the non-generic class: http://ift.tt/2iVaHDY.

And here is the .NET fiddle showing how the generic version blows up on render: http://ift.tt/2iVaHDY

The generic class worked back when I was using the LiquidType attribute. Any ideas on why it's not working with the Template.RegisterSafeType() way of registering safe types?





Aucun commentaire:

Enregistrer un commentaire