Saturday, February 6, 2010

Implementing MoveCorresponding in .Net

I started my professional career coding in COBOL and fell in love with two sweet commands:

  • Move Corresponding – which moved data between two structures (objects) if the column name and types corresponded
  • Perform Corresponding – which effective gave me a form of inheritance

I have often in later years wished that there was the equivalent in Basic, Visual Basic, C# etc., especially when I have to type 50 lines of C# code where I could have just typed one line in COBOL. In COBOL it simply invoked a comparison in the compile that wrote out the explicit instructions. In .Net, we do it on the fly, so it is not as machine efficient.

 

Well, it turns out that it is easy to write an extension for it. Whether to use the extension is a debatable topic.

  • It reduces the number of lines of code greatly
  • It causes the code to be at a higher level
  • It allows rapid code evolution because as new properties are added, there is no need to go back and update earlier code – it happens automatically.
  • On the minus side, you are not micromanaging the code

So for better or worst, here is an example of such an extension – enjoy!

using System.ComponentModel;
public static int MoveCorresponding(this object source, object dataItem)
{
    int ret = 0;
    PropertyDescriptorCollection sprops = TypeDescriptor.GetProperties(source);
    PropertyDescriptorCollection dprops = TypeDescriptor.GetProperties(dataItem);
    bool excludeId;
    if (dataItem is Control)
        excludeId = true;
    else
        excludeId = false;
    foreach (PropertyDescriptor sdesc in sprops)
        if (!excludeId || String.Compare(sdesc.Name, "Id", true) != 0)
        {
            PropertyDescriptor ddesc = dprops.Find(sdesc.Name, true);
            if (ddesc != null && !ddesc.IsReadOnly && ddesc.PropertyType == sdesc.PropertyType)
                try
                {
                    if (sdesc.GetValue(source) != ddesc.GetValue(dataItem))
                    {
                        ddesc.SetValue(dataItem, sdesc.GetValue(source));
                        ret++;
                    }
                }
                catch
                {
                    //Exceptions here are either value issues or 
                    // state issues (for example EnableTheming on web controls )
                }
        }
    return ret;
}

1 comment: