IParseable Interface

[Note: I was reminded by my roommate after posting this that static methods aren't allowed in interfaces....]

Today I was working on a JSON to NHibernate bridge when I came across something quite frustrating when trying to convert strings to other types. In this bridge object I’m persisting an object out of the database with NHibernate, then assigning the new values from the JSON string to that object. (Or list of objects.)

This seemed simple enough. I was thinking that it should be easy enough to write a loop that looks at the javascript keys {“Key”:”Value”} and matches them up with the PropertyInfo of the target object. This is trivial when both are strings, but what if the target type is a float, int, bool, date, enum etc?

Most base types have a Parse method of some kind that looks like Parse(string) or Parse(string, IFormatProvider). Here’s a couple of types that implement some variant of the Parse method.

  • System.Boolean
  • System.Byte
  • System.Char
  • System.Data.SqlTypes.SqlBoolean
  • System.Data.SqlTypes.SqlByte
  • System.Data.SqlTypes.SqlDateTime
  • System.Data.SqlTypes.SqlDecimal
  • System.Data.SqlTypes.SqlDouble
  • System.Data.SqlTypes.SqlGuid
  • System.Data.SqlTypes.SqlInt16
  • System.Data.SqlTypes.SqlInt32
  • System.Data.SqlTypes.SqlInt64
  • System.Data.SqlTypes.SqlMoney
  • System.Data.SqlTypes.SqlSingle
  • System.DateTime
  • System.DateTimeOffset
  • System.Decimal
  • System.Double
  • System.Int16
  • System.Int32
  • System.Int64
  • System.SByte
  • System.Single
  • System.TimeSpan
  • System.UInt16
  • System.UInt32
  • System.UInt64
  • System.Windows.Int32Rect
  • System.Windows.Point
  • System.Windows.Rect
  • System.Windows.Size
  • System.Windows.Vector
  • System.Net.NetworkInformation.PhysicalAddress


This leaves me with only one question?

Where’s my Interface?

I can’t do a test for IParseable on the object, I can’t even search for the parse method by name and parameters because each object implements them differently. I could go with only the string parameter which they all implement, but I’ve learned from Civ4 that culture is important, and besides I wouldn’t want to fail the Turkey test.

Of course there’s a reason for this seemingly lazy design – interfaces can’t be declared as static. (That’s a conversation for a different day.) Ok, so given that they can’t, where do we go from here? Lets pretend that we still wanted to use an Interface for these classes.

interface IParseable { }

So now we’ve got an Empty Interface. Perhaps this would be better as a custom attribute, and if so please explain to me how to accomplish this next part with said custom attribute.

We then assign our interface to the DataType and implement a number of Parse methods

    class DataType : IParseable

    {

        public static DataType Parse(string s)

        {

            //blah blah, use the string to create a new DataType

            return new DataType();

        }

    }

Then in the System.Convert class we’d implement some function like this:

    public static T Parse<T>(string s) where T : IParseable

    {

        MethodInfo mInfo = typeof(T).GetMethod(“Parse”, BindingFlags.Public | BindingFlags.Static);

        if (mInfo != null)

        {

            T obj = (T) mInfo.Invoke(null, new object[] { s });

            return obj;

        }

        return default(T);

    }

Other methods could accept CultureInfo, FormatProviders and other params. Someone have a better way of doing this?

This entry was posted in c#. Bookmark the permalink.

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>