Over the past couple of weeks I’ve been working a data validation framework. As part of this development effort I needed to listen to the events raised by DataTable instances in order to trigger automatic background validation. This validation would involve spinning through rows in the data-table and arriving at a result, flagging any errors along the way.


Unfortunately I started having problems when rows were added to the data-table and the RowChanged event got fired. You see, the RowChanged event fires BEFORE the data-table has the row added to it – I think that is kind of counter intuitive. Now its probably a bit late to change the .NET framework now, especially since there is probably a bit of code out there that relies of this behaviour, but I would like to see the addition of a number of events – like RowAdded, which only fires AFTER the data-row is accessible.


So, how did I work around it? Well, since this is really proof of concept code I had some scope to implement a bit of a dirty hack, and it goes like this.


public void InjectHack(DataTable dt)
{
  DataRowCollection collection = dt.Rows;
  Type collectionType = collection.GetType();
  FieldInfo fi = collectionType.GetField(
    “list”,
    BindingFlags.Instance | BindingFlags.NonPublic
    );
  ArrayList list = (ArrayList)fi.GetValue(collection);
  WrapperArrayList wrapperList = new WrapperArrayList(list);
  wrapperList.ItemAdded += new EventHandler(wrapperList_ItemAdded);
  fi.SetField(collection, wrapperList);
}

private void wrapperList_ItemAdded(object sender, EventArgs e)
{
  // Put the code you would expect to be able to
  // have in a handler for the RowChanged event.
}

// Filename: WrapperArrayList.cs
public class WrapperArrayList
{
  public WrapperArrayList(ArrayList list)
  {
    this.AddRange(list);
  }

  public override int Add(object value)
  {
    int index = base.Add(value);
    this.OnItemAdded(new EventArgs());
    return index;
  }

  public event EventHandler ItemAdded;
  protected void OnItemAdded(EventArgs e)
  {
    if (this.ItemAdded != null)
    {
      this.ItemAdded(this, e);
    }
  }
}


See what I mean by hack? It does work though, there are a few other ways to tackle this but they are all pretty hacky, and this is the one that I settled for. What it does is use reflection to grab the internal ArrayList that the DataRowCollection uses to store data-rows and replaces it with an instance of an ArrayList-derived class which overrides the Add method and raises an event at the right time.


I’d love to hear your ideas around a better way to do this.