samedi 8 novembre 2014

Templating from Object

The idea here is to provide a really lightweight template engine.
The point here is to demonstrate how light such a code can be. In his current state the code suffers some defaults discussed at the end.
A template is a String comprising tokens of the form [ProperyName] or [ProperyName:format]. PropertyName can be any name of any property of an object or navigable property of the object. However IEnumerable are not handled.
public static String MergeObjectFromTemplate(String st, Object o) {
    if (String.IsNullOrEmpty(st)) throw new ArgumentNullException("st");
    if (o == null) return st;

    Int32 i = st.IndexOf("[");
    Int32 j = 0;
    String pName;
    Object lo;
    String[] a;
    while (i >= 0) {
        j = st.IndexOf("]");
        if (j == -1)
            return st;

        pName = st.Substring(i + 1, j - i - 1);
        a = pName.Split(':');
        lo = GetObjectByReflection(o, a[0]);
        if (lo == null) { 
            st = st.Replace("[" + pName + "]", "_" + pName + "_");
        } else {
            if (a.Count() == 1) {
                st = st.Replace("[" + pName + "]", lo.ToString().Trim());
            } else {
                st = st.Replace("[" + pName + "]", String.Format("{0:" + a[1] + "}", lo));
            }
        }

        i = st.IndexOf("[");
    }

    return st;
}
The key function here is: GetObjectByReflection.
public static Object GetObjectByReflection(Object src, String propertyName) {
    Type type;
    Object o = src;
    foreach (String fragment in propertyName.Split('.')) {
        type = o.GetType();
        PropertyInfo pi = type.GetProperty(fragment);
        if (pi == null) {
            o = null;
            break;
        }
        o = pi.GetValue(o, null);
        if (o == null) return String.Empty;
    }

    return o;
}
That is it!
Well, not totally. It remains some defaults, but for 50 lines, that's may be not so bad. Known defaults are:

  • Bad format string are not handled.
  • This is blocking, if throwing an exception is blocking. Correcting it is easy once expected behavior is known. At the time the code was updated I was just needing to format DateTime in a relatively safe environment: templates are edited by me. It is another story if you want to allow user to produce templates.
  • Excepted for a bad format String, the code always returns a String, even if a bad object is provided, or bad property name is used.

Aucun commentaire:

Enregistrer un commentaire