DataGrid and Web Services

Didya ever wonder?... why DataGrids and other data-bound controls can use arrays of objects as data sources, but they display only public properties (not fields)? On the other hand, types generated by wsdl.exe or xsd.exe generally expose public fields (not properties). Do you think the xsd.exe people talked to the DataGrid people?  

Ok, I know, this isn't an interop issue. But it is indirectly related to interop. See, if you are connecting to remote systems via webservices and you want to display the result in a databound control, this issue arises. Or, if you are exchanging XML documents between cooperating applications via some other mechanism (like a reliable queue, or directly over HTTP as in REST). In this case you will probably want to use XML Serialization, and you might again want display the result into a data-bound control. What are you gonna do? 

  • Manually create DataRows and Datacolumns? Ahh, only if you get paid per line of code.
  • Use a DataSet? Nope, for web services, that only works in .NET-to-.NET calls (have you ever heard of Java?), and it won't work with XML Serialization.
  • Ok, then I guess we should Hand-code a new custom type for every different type? (this is the approach taken in this MSDN article from January 2003). This works, but involves writing code for every new scenario. For the lazy types (like me), this isn't going to fly.

I understand this is changing for Whidbey, where you'll be able to bind on public fields or properties - someone correct me if I am wrong here. But what if you have .NET v1.1 ? Is there any joy? Hmmm.... What if.... you could auto-magically transform a class with fields into a class that exposes public properties? 

Auto-magically? Yes, through the magic of reflection. This sample shows a general solution for how to morph types with public fields - something you might get from a web service or from XML Serialization - into types with public properties - something a data-bound control can use. The approach is to dynamically generate a type, at runtime, and then convert the array of type1 into an array of type2, and use type2 as the DataSource for the data-bound control. eg,

// call web service, get array of types with public fields
glue.webservice.OrderInfo[] oia= wsproxy.getOrdersForCustomer(TextBox1.Text);
// generate a morphed array suitable for use in a DataGrid:
DataGrid1.DataSource= MorphArray(oia);

Because this example uses System.CodeDom to generate the type, it also serves as a short illustration of how to use that nifty technology.

Some links
Here's the code.
Commentary on REST and SOAP by Dare