Meta Maker C#

Few days ago someone asked, and I dutifully obliged. The “requirement” was to develop (quickly of course) one “simple .net page”, that will show the properties of the Request.Browser (.NET object), to the browser user. Which (again very quickly) turned out to be a very different requirement. Because it turned out that “show in the browser” actually meant: “send back to JavaScript behind a browser page that called you…”. Ok, not to worry here we go …

Of course this “simple page” is actually an server side component (implemented as an ui-less aspx). Which obviously will grow in complexity very quickly and very often, as it (by now) seems. Therefore, I needed some design here, instead of the (for some developers) usual: “just do it quick and dirty, till 5:30″, ad-hoc code, which will make changes more and more expensive and time consuming, as time passes by, old requirements keep on changing and new ones keep on coming.

This component will be obviously asked to return objects encoded as JSON strings. Many different kind of objects from many diferent server side sources or .net objects. First example requirement being properties of the server side Browser object, that is made for each Request by looking into HTTP Server variables made after the connection with the exact browser. Next example might be some “home made” Configuration object. And so on. Obviously client side developers will want to use this to see what is “lurking” on the server side, of their AJAX app.

Ok, I realized this is a time for (yet another) Factory implementation. And then, I confidently went along to do this with a “help” of C# generics.
Just to quickly realize the height of stone walls C# raises in front of someone coming from C++, perusing his C++ templates experience. In short: C# generics are very restrictive (when compared to C++) and one can not simply transfrom C++ template concepts, into C#. It is actually impossible and it requires paradigm shift. Different thinking altogether. Different designs and implementation idioms. After some wrestling with C# idioms, this is what I came up with.

/*
GPL (c) 2009-2010 by DBJ.ORG
 */
using System;

public partial class Composer : System.Web.UI.Page
{
    /// <summary>
    /// Role: transform property name/value pair into the json object
    /// </summary>
    /// <param name="host">host of the property</param>
    /// <param name="pi_">info type of the property</param>
    /// <returns>json object</returns>
    string prop_value_json (object host, System.Reflection.PropertyInfo pi_)
    {
        string retval = "";
        try {
            if (pi_.CanRead) {
                if (pi_.PropertyType.IsNotPublic) retval = "NOT PUBLIC";
                else if (pi_.IsSpecialName) retval = "SPECIAL NAME";
                else retval = pi_.GetValue(host, null).ToString();
            }
            else {
                retval = "CAN NOT READ";
            }
        }
        catch (System.Exception x) {
            retval = x.Message;
        }
        return  string.Format("'{0} \"{1}\" : \"{2}\" {3}'", "{", pi_.Name , retval, "}" ) ;
    }
 //----------------------------------------------------
    protected void Page_Load(object sender, EventArgs e)
    {
// use the browser property from the request object
        System.Web.HttpBrowserCapabilities browser = this.Request.Browser;
// start the javascript code generation, that will send back
        string js = "var properties = [ '" + browser.GetType().Name + "', " ;
// use our iterate_over method to encapsulate browsers properties collection
// and exposure for iteration
// NOTE: type of the iterator is correlated to the second argument
        foreach (System.Reflection.PropertyInfo member
            in
           iterate_over(
              browser, typeof(System.Reflection.PropertyInfo))
            )
        {
            js += (prop_value_json(browser, member) + " ,");
        }

// finish the javascript code, close the array declaration
        js += "]" ;
// remove the last comma and add code to write the array of properties
// on the browser page
        js = js.Replace(",]", "]; document.write(properties.join('<br/>'));");
// set the proper content type so that browser can handle properly
// the reply as a javascript source code.
        this.Response.ContentType = "text/javascript";
        this.Response.Write(js);
    }

#region GPL (c) 2009 by DBJ -- GIF (aka: "Generic Iteration Framework")
    System.Collections.IList iterate_over
      (object host_, System.Type what_)
    {
        return meta_maker(what_)(host_);
    }

    delegate System.Collections.IList list_maker(object host_);

    list_maker meta_maker( System.Type what_ )
    {
        if( what_.Equals( typeof(System.Reflection.PropertyInfo)))
        return make_list_of_properties;

        if (what_.Equals(typeof(System.Reflection.MethodInfo)))
            return make_list_of_methods;

        throw new System.ApplicationException(
          "Type [" + what_.Name + "] not handled by meta_maker()"
       );
    }

    System.Collections.Generic.List<System.Reflection.PropertyInfo>
        make_list_of_properties(object host_)
    {
        return new System.Collections.Generic.List
             <System.Reflection.PropertyInfo>
                 ( host_.GetType().GetProperties() ) ;
    }
    System.Collections.Generic.List<System.Reflection.MethodInfo>
        make_list_of_methods(object host_)
    {
        return new System.Collections.Generic.List
            <System.Reflection.MethodInfo>
                (host_.GetType().GetMethods());
    }
    #endregion
}

In essence above is a generic solution with a minimal amount of C# generics. And with an use of System.Type explicitly, instead of wrestling with C# generics, which are using it implicitly. In the C# context, the amount of genericity is actually restricted by the restrictions of C# generics concepts. For example like an requirement for an obligatory default constructor. Or like completely redundant concept of “constraints” which are apparently invented to “enforce the type safety” ? Why, is a very moot point.
Obviously legacy C# posed a big problem when generics have been in development. To solve the problems Constraints have been invented, together with some story on why are they actually good for you. While in reality “constraints” in C# are nothing else but scaffolding that helps the C# compiler to create concrete type instances of generic classes. Because it can not deduce what it needs, on its own, in order to be able to create them. This is very serious drawback for C# which is already rich in non obvious “features” which otherwise can be described as: “design flaws”.

Ok, back to my solution. The ‘Maker’ (meta_maker above) pattern, is a little brother of the Factory Pattern. Sometimes it is called “Factory Method”. This indicates it is usually implemented in a single function. I think realistically, my solution can be extended to achieve some level of genericity and reusability. And to have a maneuvring space for extending this POC and design into the fully configurable solution.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>