Search code examples
c#if-statementenumsdotliquid

If block on SafeTypes not working


I am currently working on a project and we have certain needs where we need to use Enums in the templates themselves. I created the following class to allow me to access my enums inside a DotLiquid template.

/// <summary>
/// Liquid Component created to provide support for specified Enumerations.
/// </summary>
public class EnumSupportComponent : ILiquidComponent
{
    private readonly static Type[] EnumTypes =
    {
        typeof(DeliveryType),
        typeof(MessageFormat),
        typeof(OrderMethod),
        typeof(PaymentMethod)
    };

    public void Register()
    {
        foreach (Type type in EnumTypes)
        {
            Template.RegisterSafeType(type, LocalizeEnum);
        }
    }

    /// <summary>
    /// Localizes an enum.
    /// </summary>
    /// <param name="o">Object (enum member) to localize.</param>
    /// <returns></returns>
    private static object LocalizeEnum(object o)
    {
        var objType = o.GetType();
        var value = LocalizationHelper.GetLocalizedValue(o, objType);
        return value;
    }

    /// <summary>
    /// Map the variables to the right spot.
    /// </summary>
    /// <param name="parameters"></param>
    public static void MapVariables(RenderParameters parameters)
    {
        foreach (Type enumType in EnumTypes)
        {
            var members = enumType.GetEnumValues();

            foreach (var member in members)
            {
                var key = String.Format("{0}.{1}", enumType.Name, member);
                parameters.LocalVariables.Add(key, LocalizeEnum(member));
            }
        }

    }
}

The Register method is called by my IoC Container and the "LiquidComponent" is indeed registered with no problem. However, when my templates hits the following point, it always falls in the else block and I don't understand why. There are no errors, simply a wrong result.

<tr>
    <th style="text-align: left; padding-right: 10px;">Transaction status:</th>
    <td style="padding: 5px 0px;">
        {% if Model.PaymentMethod == PaymentMethod.Online %}
            {{ Model.TransactionStatus }}
        {% else %}
            N/A
        {% endif %}
    </td>
</tr>

I'm out of idea for resolving this. I though that {{ Model.PaymentMethod }} would be interpreted as a string at that point, but it's not the case. I removed the localization to only have the enum itself, but the behavior is the same (with the fact that the enum is no longer localized). I would like to avoid to create a new Block to test equality in this case. I searched online, but there seem to be no answer.

I also posted the question on the official forum : https://groups.google.com/forum/#!topic/dotliquid/hU4hnOYjCnY


Solution

  • The problem might be in MapVariables:

    var key = String.Format("{0}.{1}", enumType.Name, member);
    parameters.LocalVariables.Add(key, LocalizeEnum(member));
    

    I don't think adding a key with a "." in it will work as you expect (and it should probably throw an exception). Also, isn't member an integer, so won't key end up being something like PaymentMethod.0?

    You could try this:

    foreach (Type enumType in EnumTypes)
    {
        var members = enumType.GetEnumValues();
        var enumWrapper = new Dictionary<string, object>();
    
        foreach (var member in members)
            valueWrapper.Add(enumType.GetEnumName(member), member);
    
        parameters.LocalVariables.Add(enumType.Name, enumWrapper);
    }
    

    (I've ignored LocalizeEnum because I don't know if it returns a string or an integer.)

    You could use the debugger to check what's in parameters.LocalVariables just prior to rendering, and verify that it's as you expect.