Tag Archives: GetType

Invoke base class methods on unknown types

I recently built a system that dynamically builds content for sending messages to users after certain events.  As is with most of these types of systems the content is mostly static and stored in a repository with “holder values” that are replaced at run time from a data source.  The architecture of this system is one that is very configurable.  Meaning, a new message can be created using configuration files no additional coding necessary.  One of the challenges this presented was how to handle formatting of data types that are not known until run time.

Use Case:

The content may look something like: “Your bill with a billing date of _date for _amount is overdue.”  The holder values are _date and _amount; the data source might store the amount as a number and the date including the time (100 & 12/31/2012 08:35:55).  However, this data would need to be formatted as $100.00 and 12/31/2012 for a user facing message.

The system needed to handle any possible formatting of data without knowing at build time what they might be.  To accomplish that I store a pointer to a data source for each “holder value”, which includes a mapping to a base class method (and the required parameters) of the underlying data type.  Then, when replacing holder values with the  real values from the data source I apply the method using reflection.

Here’s some sample code and a quick explanation:

public static string InvokeSomeMethod(string method, string parameters, string value)

        {
            Object v = ConvertValue(value);
            var pList = ParseMethodParameters(parameters);
            var rt = v.GetType().GetMethod(method, GetParameterTypes(pList)).ReturnType.FullName;
            return InvokeMethod(v, rt, method, pList);
        }
}

“Let me explain. No, there is too much. Let me sum up”:

We can’t just invoke a method all willy nilly like, first we need to know a few more things.

  • What type are we dealing with?
  • What is the return type of the method? (Beware of overloads)

A little more detail:

Type:

The values I’m dealing with are strings, however, I may need to execute a method on it’s “true” type.  In order to get the type I call ConvertValue (line 1 above) which passes the value through a series of tests to determine what type it is and convert it.  I won’t bore you with the entire method, but this should give you an idea what I mean.

 public static object ConvertValue(string value)
        {
            if (ParameterIsInt(value))
            {
                return Convert.ToInt32(value);
            }
            if (ParameterIsDouble(value))
            {
                return Convert.ToDouble(value);
            }
              if (ParameterIsDate(value))
            {
                 return Convert.ToDateTime(value);
            }
        }
}

Each sub-function does something like this:

 public static bool ParameterIsDate( string value)
        {
            DateTime d;
             bool result = DateTime.TryParse(value,  out d);
             if (result)
            {
                 return true;
            }
             else
            {
                 return false;
            }
        }

Return Type and the Parameter List:

Remember above where I said beware of overloads when getting the return type.  The parameter list has to be parsed and passed when getting the method return type in order to get the correct method. When I parse the list I reuse the convert value function to get the correct type of the parameter, this is key to the getting the method.  And of course the parsed parameters are passed when invoking the method.

Conclusion:

So far this method (as part of a larger highly flexible system) has worked very well and allowed us to create a lot of new content with little to no new lines of code.  One down side, the person building the configurations has to  know the base class methods and parameters (absent a user interface for the content management) to format the data.  Another issue was the convert value function.  When I originally built the system I just added the half dozen or so common data types.  However, if a new one comes up some coding will have to be added.  I do have a possible solution to that issue.  In some other similar systems I’ve used Convert.Change Type to change strings to the “real type”.  This works well as long as you know what type you want.  If not, your still forced to call the various try parse methods to get the type.  In a system like the one were using, we could leverage the configuration to pass a type to the Convert.ChangeType method and get rid of the try parse convert to methods.  I’ll probably add that the first time I have a new data type come up, so far it hasn’t.

Advertisements

%d bloggers like this: