Patching polymorphic pain at runtime

In the last post, we saw that data binding in ASP.NET doesn’t support polymorphism. We also saw that we could mitigate the problem by using simple wrapper types. Writing such wrappers by hand won’t kill you, but it is fairly brain-dead. I mentioned that an alternative would be to generate the wrappers at runtime, using reflection. That actually sounds like a bit of fun, so let’s see how it can be done. If nothing else, it’s a nice introductory lesson in using Reflection.Emit.

Comeback of the canines

As an example, let’s revisit our two four-legged friends and one enemy from the previous post: the Dog, the Chihuahua and the Wolf. They all implement ICanine.

The canines have gained a skill since last time, though – they can now indicate whether or not they’ll enjoy a particular kind of food. The code looks like this:


public enum Food { Biscuit, Meatballs, You }
public interface ICanine
{
string Bark { get; }
bool Eats(Food f);
}
public class Wolf : ICanine
{
public virtual string Bark { get { return "Aooo!"; } }
public bool Eats(Food f) { return f != Food.Biscuit; }
}
public class Dog : ICanine
{
public virtual string Bark { get { return "Woof!"; } }
public virtual bool Eats(Food f) { return f != Food.You; }
}
public class Chihuahua : Dog
{
public override string Bark { get { return "Arff!"; } }
public override bool Eats(Food f) { return f == Food.Biscuit; }
}

view raw

Canines.cs

hosted with ❤ by GitHub

What we want to do in our web application is display a grid that shows the canine’s eating preferences as well as its bark. This calls for a combination of auto-generated and custom columns: an automatic one for the Bark property, and a custom one for each kind of food.

The DataGrid is declared in the .aspx page:


<asp:DataGrid
ID="_grid"
runat="server"
AutogenerateColumns="true"
FontSize="X-Large"
FontNames="Consolas"
HeaderStyleBackColor="LightBlue" />

view raw

DataGrid.cs

hosted with ❤ by GitHub

This gives us a column for the Bark out of the box.

In the code-behind, we add a column for each kind of food. We also get a list of canines, which we wrap in something called an BoxEnumerable<ICanine> before binding to it.


protected void Page_Load(object sender, EventArgs e)
{
GetGridColumns().ForEach(f => _grid.Columns.Add(f));
_grid.DataSource = new BoxEnumerable<ICanine>(GetCanines());
_grid.DataBind();
}
private static List<DataGridColumn> GetGridColumns()
{
return new List<DataGridColumn>
{
new TemplateColumn
{
HeaderText = "Biscuits?",
ItemTemplate = new FoodColumnTemplate(Food.Biscuit)
},
new TemplateColumn
{
HeaderText = "Meatballs?",
ItemTemplate = new FoodColumnTemplate(Food.Meatballs)
},
new TemplateColumn
{
HeaderText = "You?",
ItemTemplate = new FoodColumnTemplate(Food.You)
}
};
}
private static IEnumerable<ICanine> GetCanines()
{
return new List<ICanine> {new Dog(), new Wolf(), new Chihuahua() };
}

view raw

GridColumns.cs

hosted with ❤ by GitHub

The food preference columns use an ItemTemplate called FoodColumnTemplate. It’s a simple example of data binding which goes beyond mere properties, since we’re invoking a method on the data item:


class FoodColumnTemplate : ITemplate
{
private readonly Food _food;
public FoodColumnTemplate(Food food)
{
_food = food;
}
public void InstantiateIn(Control container)
{
var label = new Label();
label.DataBinding += OnDataBinding;
container.Controls.Add(label);
}
private void OnDataBinding(object sender, EventArgs e)
{
var label = (Label) sender;
var row = (DataGridItem) label.NamingContainer;
var canine = (ICanine) row.DataItem;
label.Text = canine.Eats(_food) ? "Yes" : "No";
}
}

If we run the application, we get the result we wanted:

Foods-result

Without the presence of the BoxEnumerable<ICanine> above, though, we’d have a runtime exception at our hands. Under the covers, BoxEnumerable<ICanine> is producing the necessary wrappers around the actual canines to keep the DataGrid happy.

How it works

Let’s see how we can do this. Here’s an overview of the different moving parts:

Box-overview

That’s a fair amount of types, but most of them have trivial implementations. Consider BoxEnumerable<T> first:


public class BoxEnumerable<T> : IEnumerable<Box<T>>
{
private readonly IEnumerable<T> _;
public BoxEnumerable(IEnumerable<T> e)
{
_ = e;
}
public IEnumerator<Box<T>> GetEnumerator()
{
return new BoxEnumerator<T>(_.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

As you can see, it’s really the simplest possible wrapper around the original IEnumerable<T>, turning it into an IEnumerable<Box<T>>. It relies on another wrapper type, BoxEnumerator<T>:


public class BoxEnumerator<T> : IEnumerator<Box<T>>
{
private readonly IEnumerator<T> _;
private readonly BoxFactory<T> _factory = new BoxFactory<T>();
public BoxEnumerator(IEnumerator<T> e)
{
_ = e;
}
public void Dispose()
{
_.Dispose();
}
public bool MoveNext()
{
return _.MoveNext();
}
public void Reset()
{
_.Reset();
}
public Box<T> Current
{
get { return _factory.Get(_.Current); }
}
object IEnumerator.Current
{
get { return Current; }
}
}

That too is just a minimal wrapper. The only remotely interesting code is in the Current property, where a BoxFactory<T> is responsible for turning the T instance into a Box<T> instance. BoxFactory<T> looks like this:


public class BoxFactory<T>
{
private readonly Box<T> _ = EmptyBoxFactory.Instance.CreateEmptyBox<T>();
public Box<T> Get(T t)
{
return _.Create(t);
}
}

view raw

BoxFactory.cs

hosted with ❤ by GitHub

This is short but a little weird, perhaps. For fun, we’re adding a dash of premature optimization here. We’re using EmptyBoxFactory to create an “empty” instance of Box<T> (that is, without an instance of T inside). The BoxFactory<T> holds on to that empty instance for the rest of its lifetime, and uses it to create “populated” boxes. In other words, the initial empty box acts as a prototype for all subsequent boxes. That way, we avoid using reflection more than once to create the boxes. This should make people who fear the performance penalty of reflection a little happier. Let’s see how the prototype creates populated boxes for the factory:


public Box<T> Create(T t)
{
var box = (Box<T>) MemberwiseClone();
box._ = t;
return box;
}

view raw

CreateBox.cs

hosted with ❤ by GitHub

Easy as pie, we’re just cloning and setting the protected T field. Doesn’t get much simpler than that.

It’s time to start worrying about the box itself, though. Of course, this is where things get both non-trivial and interesting.

So the goal is to create a type at runtime. The type should be used to wrap each item in an IEnumerable<T>, so that the control’s DataSource is set to a perfectly homogenous IEnumerable. That is, it will only contain instances of the same concrete type. The wrapper type won’t have any intelligence of its own, it will merely delegate to the wrapped instance of T.

To support auto-generation of columns, the wrapper type must have the same public properties as T. (We won’t consider the option of masking or renaming properties – that’s a use case that goes beyond just fixing what is broken.) In the case of T being an interface, a viable option would be for the wrapper type to implement T. However, we need the wrapper to work for all kinds of T, including when T is a base class with one or more non-virtual members. In the general case, therefore, the wrapper must simply mimic the same properties, duck typing-style.

Auto-generation of columns is pretty nifty, and a property-mimicking wrapper is sufficient for that scenario. For more sophisticated data binding scenarios, though, you need to be able to call arbitrary methods on the item we’re binding to. To do so in the general case (where T might be a class), we need some way of shedding the wrapper. We can’t simply call the methods on the wrapper itself, since we don’t have access to the name of the dynamically generated wrapper type at compile time. The C# compiler wouldn’t let us (well, we could use dynamic, but then we’re giving up static typing). So we’ll be using an Unwrap method, giving us access to the bare T. (Note that we can’t use a property, since that would show up when auto-generating columns!)

Now how can we call Unwrap if the type doesn’t even exist at compile time? Well, we know that there’s a small set of core capabilities that all wrapper types are going to need: the wrapped instance of T, and a way of wrapping and unwrapping T. So let’s create an abstract base class containing just that:


abstract class Box<T>
{
protected T _;
public T Unwrap() { return _; }
public Box<T> Create(T t)
{
var box = MemberwiseClone();
box._ = t;
return box;
}
}

view raw

Box.cs

hosted with ❤ by GitHub

That way, we can always cast to Box<T>, call Unwrap, and we’re good.

Why are we calling it a “box”, by the way? It’s sort of a tip of the hat to academia, of all things. According to this paper on micro patterns, a “box” is “a class which has exactly one, mutable, instance field”. That suits our implementation to a T (hah!) so “box” it is.

The concrete box for our example should conceptually look like this:


public class BoxedICanine : Box<ICanine>, ICanine
{
public string Bark
{
get { return _.Bark; }
}
public bool Eats(Food f)
{
return _.Eats(f);
}
}

view raw

BoxedICanine.cs

hosted with ❤ by GitHub

Of course, the boxes we generate at runtime will never actually have a C# manifestation – they will be bytecode only. At this point though, the hand-written example will prove useful as target for our dynamically generated type.

Note that we’re going to try to be a little clever in our implementation. In the case where T is an interface (like ICanine), we’re going to let the dynamically generated box implement the original interface T, in addition to extending Box<T>. This will allow us to pretend that the box isn’t even there during data binding. You might recall that we’re casting to ICanine rather than calling Unwrap in the FoodColumnTemplate, even though the data item is our dynamically generated type rather than the original canine. Obviously we won’t be able to pull off that trick when T is a class, since C# has single inheritance.

Looking at the bytecode for BoxedICanine in ILDASM, ILSpy or Reflector, you should see something like this (assuming you’re doing a release compilation):


.class public auto ansi beforefieldinit BoxedICanine
extends PolyFix.Lib.Box`1<class PolyFix.Lib.ICanine>
implements PolyFix.Lib.ICanine
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void PolyFix.Lib.Box`1<class PolyFix.Lib.ICanine>::.ctor()
L_0006: ret
}
.method public hidebysig newslot virtual final instance bool Eats(valuetype PolyFix.Lib.Food f) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldfld !0 PolyFix.Lib.Box`1<class PolyFix.Lib.ICanine>::_
L_0006: ldarg.1
L_0007: callvirt instance bool PolyFix.Lib.ICanine::Eats(valuetype PolyFix.Lib.Food)
L_000c: ret
}
.method public hidebysig specialname newslot virtual final instance string get_Bark() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldfld !0 PolyFix.Lib.Box`1<class PolyFix.Lib.ICanine>::_
L_0006: callvirt instance string PolyFix.Lib.ICanine::get_Bark()
L_000b: ret
}
.property instance string Bark
{
.get instance string PolyFix.Lib.BoxedICanine::get_Bark()
}
}

view raw

BoxedICanine.il

hosted with ❤ by GitHub

This, then, is what we’re aiming for. If we can generate this type at runtime, using ICanine as input, we’re good.

IL for beginners

If you’re new to IL, here’s a simple walk-through of the get_Bark method. IL is a stack-based language, meaning it uses a stack to transfer state between operations. In addition, state can be written to and read from local variables.

The .maxstack 8 instruction tells the runtime that a stack containing a eight elements will be sufficient for this method (in reality, the stack will never be more than a single element deep, so eight is strictly overkill). That’s sort of a preamble to the actual instructions, which come next. The ldarg.0 instruction loads argument 0 onto the stack, that is, the first parameter of the method. Now that’s confusing, since get_Bark seems to have no parameters, right? However, all instance methods receive a reference to this as an implicit 0th argument. So ldarg.0 loads the this reference onto the stack. This is necessary to read the _ instance field, which happens in the ldfld !0 instruction that follows. The ldfld !0 pops the this reference from the stack, and pushes the reference held by the 0th field (_) back on. So now we got an reference to an ICanine on there. The following callvirt instruction pops the ICanine reference from the stack and invokes get_Bark on it (passing the reference as the implicit 0th argument, of course). When the method returns, it will have pushed its return value onto the stack. So there will be a reference to a string there. Finally, ret returns from the method, leaving the string reference on the stack as the return value from the method.

If you take a look at the Eats method next, you’ll notice it’s practically identical to get_Bark. That’s because we’re essentially doing the same thing: delegating directly to the underlying T instance referenced by the _ field.

Now, how can we generate stuff like this on the fly?

Creating a type at runtime

As you can see below, a .NET type lives inside a module that lives inside an assembly that lives inside an appdomain.

Appdomain-blue

So before we can start generating the actual type, we need to provide the right environment for the type to live in. We only want to create this environment once, so we’ll do it inside the constructor of our singleton EmptyBoxFactory:


private readonly ModuleBuilder _moduleBuilder;
private EmptyBoxFactory()
{
const string ns = "PolyFix.Boxes";
_moduleBuilder = Thread.GetDomain()
.DefineDynamicAssembly(new AssemblyName(ns), AssemblyBuilderAccess.Run)
.DefineDynamicModule(ns);
}

AssemblyBuilderAccess.Run indicates that we’re creating a transient assembly – it won’t be persisted to disk. We’re holding on to the module builder, which we’ll use when creating types later on. Assuming that we’ll be using the BoxEnumerable<T> in multiple data binding scenarios (for various Ts), the module will be accumulating types over time.

The public API of EmptyBoxFactory is limited to a single method, CreateEmptyBox. It uses reflection to create an instance of the appropriate type.


public Box<T> CreateEmptyBox<T>()
{
return (Box<T>)Activator.CreateInstance(GetBoxType<T>());
}

Creating the instance is simple enough (albeit slower than newing up objects the conventional way). The real work lies in coming up with the type to instantiate, so we need to move on! GetBoxType<T> looks like this:


private Type GetBoxType<T>()
{
var t = typeof(T);
string typeName = t.FullName + "Box";
foreach (var existingType in _moduleBuilder.GetTypes())
{
if (existingType.FullName == typeName)
{
return existingType;
}
}
return CreateBoxType(t, typeof (Box<T>), typeName);
}

view raw

GetBoxType.cs

hosted with ❤ by GitHub

We’re still treading the waters, though. Specifically, we’re just checking if the module already contains the suitable box type – meaning that we’ve been down this road before. Assuming we haven’t (and we haven’t, have we?), we’ll go on to CreateBoxType. Hopefully we’ll see something interesting there.


public Type CreateBoxType(Type t, Type boxType, string typeName)
{
var boxBuilder = _moduleBuilder.DefineType(
typeName, TypeAttributes.Public, boxType, t.IsInterface ? new[] {t} : new Type[0]);
var f = boxType.GetField("_", BindingFlags.Instance | BindingFlags.NonPublic);
return new BoxTypeFactory(t, boxBuilder, f).Create();
}

Oh man, it seems we’re still procrastinating! We haven’t reached the bottom of the rabbit hole just yet. Now we’re preparing for the BoxTypeFactory to create the actual type.

Two things worth noting, though. One thing is that if t is an interface, then we’ll let our new type implement it as mentioned earlier. This will let us pretend that the box isn’t even there during data binding. The other thing is that we’re obtaining a FieldInfo instance to represent the _ field of BoxType<T>, which as you’ll recall holds the instance of T that we’ll be delegating all our method calls and property accesses to. Once we have the FieldInfo, we can actually forget all about BoxType<T>. It’s sort of baked into the TypeBuilder as the superclass of the type we’re creating, but apart from that, BoxTypeFactory is oblivious to it.

But now! Now there’s nowhere left to hide. Let’s take a deep breath, dive in and reflect:


class BoxTypeFactory
{
private readonly Type _type;
private readonly TypeBuilder _boxBuilder;
private readonly FieldInfo _field;
private readonly Dictionary<string, MethodBuilder> _specials = new Dictionary<string, MethodBuilder>();
public BoxTypeFactory(Type type, TypeBuilder boxBuilder, FieldInfo field)
{
_type = type;
_boxBuilder = boxBuilder;
_field = field;
}
public Type Create()
{
foreach (MethodInfo m in _type.GetMethods())
{
if (!IsGetType(m)) CreateProxyMethod(m);
}
foreach (PropertyInfo p in _type.GetProperties())
{
ConnectPropertyToAccessors(p);
}
return _boxBuilder.CreateType();
}
private static bool IsGetType(MethodInfo m)
{
return m.Name == "GetType" && m.GetParameters().Length == 0;
}
private void CreateProxyMethod(MethodInfo m)
{
var parameters = m.GetParameters();
// Create a builder for the current method.
var methodBuilder = _boxBuilder.DefineMethod(m.Name,
MethodAttributes.Public | MethodAttributes.Virtual,
m.ReturnType,
parameters.Select(p => p.ParameterType).ToArray());
var gen = methodBuilder.GetILGenerator();
// Emit opcodes for the method implementation.
// The method should just delegate to the T instance held by the _ field.
gen.Emit(OpCodes.Ldarg_0); // Load 'this' reference onto the stack.
gen.Emit(OpCodes.Ldfld, _field); // Load 'T' reference onto the stack (popping 'this').
for (int i = 1; i < parameters.Length + 1; i++)
{
gen.Emit(OpCodes.Ldarg, i); // Load any method parameters onto the stack.
}
gen.Emit(m.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, m); // Call the method.
gen.Emit(OpCodes.Ret); // Return from method.
// Keep reference to "special" methods (for wiring up properties later).
if (m.IsSpecialName)
{
_specials[m.Name] = methodBuilder;
}
}
private void ConnectPropertyToAccessors(PropertyInfo p)
{
var paramTypes = p.GetIndexParameters().Select(ip => ip.ParameterType).ToArray();
var pb = _boxBuilder.DefineProperty(p.Name, p.Attributes, p.PropertyType, paramTypes);
WireUpIfExists("get_" + p.Name, pb.SetGetMethod);
WireUpIfExists("set_" + p.Name, pb.SetSetMethod);
}
private void WireUpIfExists(string accessor, Action<MethodBuilder> wireUp)
{
if (_specials.ContainsKey(accessor))
{
wireUp(_specials[accessor]);
}
}
}

Oh. That’s almost anti-climatic – it’s not really hard at all. The Create method is super-simple: create proxy methods for any public methods in the type we’re wrapping, wire up any properties to the corresponding getter and/or setter methods, and we’re done! CreateProxyMethod seems like it might warrant some explanation; however, all we’re really doing is copying verbatim the IL we looked at in our walkthrough of get_Bark earlier. The wiring up of properties is necessary because a property consists of two parts at the IL level, a .property thing and a .method thing for each accessor. That, too, we saw in the IL of the hand-written class. So there’s really not much to it.

You might note that we’re explicitly not creating a proxy for the GetType method, defined on System.Object. This applies to the case where the type we’re boxing is a class, not an interface. In general, we shouldn’t proxy any non-virtual methods inherited from System.Object, but in practice that’s just GetType. So we’re taking the easy way out. (Note that the .NET runtime wouldn’t actually be fooled if we did inject a lying GetType implementation – it would still reveal the actual type of the object. Still, it’s better to play by the book.)

We will be providing proxies for virtual methods, though (e.g. Equals, GetHashCode and ToString). This makes the box as invisible as possible.

Afterthought: Anonymous types

There’s actually an alternative way of getting around the problem with broken polymorphism in simple scenarios. Rather than hand-writing your own wrapper or generating one at runtime, you can have the C# compiler generate one for you at compile time, using anonymous types. In fact, you can approximate a working solution for our example just by doing this in the code-behind:


protected void Page_Load(object sender, EventArgs e)
{
_grid.DataSource = GetCanines().Select(
c => new {
Biscuit = c.Eats(Food.Biscuit),
Meatballs = c.Eats(Food.Meatballs),
You = c.Eats(Food.You),
c.Bark
});
_grid.DataBind();
}

view raw

Canines.Anon.cs

hosted with ❤ by GitHub

Note that you don’t add any custom columns in this case, it’s all auto-generated. Running the application, you get this:

Food-result-anon

It’s not exactly the same as before, but it’s pretty close. Unfortunately, the approach isn’t very flexible – it breaks down as soon as you want to display something that’s not just text in the grid. For instance, say you want something like this:

Food-dropdown

Anonymous types won’t help you, but the runtime wrapper will (as will a hand-written one, of course). You just need a suitable ITemplate:


public class FoodListColumnTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
var list = new DropDownList();
list.DataBinding += OnDataBinding;
container.Controls.Add(list);
}
private void OnDataBinding(object sender, EventArgs e)
{
var list = (DropDownList) sender;
var row = (DataGridItem) list.NamingContainer;
var canine = (ICanine) row.DataItem;
Action<Food> add = food => { if (canine.Eats(food)) { list.Items.Add(food.ToString()); } };
add(Food.Biscuit);
add(Food.Meatballs);
add(Food.You);
}
}

So…

Turns out that generating types at runtime is no big deal. It provides a flexible solution to the data binding problem, without the need for mindless hand-written wrappers.

As usual, let me know if you think there’s something wrong with the approach or the implementation. Also, I’d love to hear it if you have a different solution to the problem.


Polymorphic pain in ASP.NET data binding

I recently found out – the hard way, of course – that data binding in ASP.NET is broken with respect to polymorphism. It’s not consistently broken, though – it depends on the particular control you’re using. Makes life as a programmer that much more interesting, doesn’t it?

Let’s consider a very simple example. We have a type hierarchy like the following:

Canine-hierarchy

There’s an ICanine interface, with implementing classes Wolf and Dog. Chihuahua is a subclass of the latter. The code looks like this:


interface ICanine
{
string Bark { get; }
}
class Wolf : ICanine
{
public virtual string Bark { get { return "Aooo!"; } }
}
class Dog : ICanine
{
public virtual string Bark { get { return "Woof!"; } }
}
class Chihuahua : Dog
{
public override string Bark { get { return "Arff!"; } }
}

view raw

ICanine1.cs

hosted with ❤ by GitHub

Now we’d like to conjure up a collection of canines and bind to them. Sounds innocent enough, right? And it is, if you use one of the benign controls. “Benign” as in “not badly broken”. ListBox is one of those. We create an IEnumerable<ICanine> like so:


var canines = new List<ICanine> { new Dog(), new Wolf(), new Chihuahua() };

view raw

CanineList.cs

hosted with ❤ by GitHub

And then we do the two-step song-and-dance of ASP.NET data binding (assuming that _box is an instance of ListBox):


_box.DataSource = canines;
_box.DataBind();

We run it, and get the following result:

Bark-listbox

Presto! All is well! What is this guy talking about? Broken polymorphism? Where?

Well, that was the benign control, remember? Here’s a malicious one: DataGrid.

We do the exact same thing, except using _grid of the obvious type:


_grid.DataSource = canines;
_grid.DataBind();

We run it, and get…

Exception-grid-wolf

Ouch.

Evidently, there’s some reflection voodoo going on underneath the hood when you’re doing data binding in ASP.NET. And in the case of DataGrid, that voodoo is just too feeble.

Now, consider a variation of the code above, omitting the Wolf. Wolves are trouble after all.


var canines = new List<ICanine> { new Dog(), new Chihuahua() };
_box.DataSource = canines;
_box.DataBind();

This time…

Bark-grid-dogs

It works! Oh man, that’s weird. So apparently subclassing works as long as there’s a common base class? You wish. Let’s try this instead:


var canines = new List<ICanine> { new Chihuahua(), new Dog() };
_box.DataSource = canines;
_box.DataBind();

view raw

Canine.Var2.cs

hosted with ❤ by GitHub

That is, we reverse the order, passing in the Chihuahua first, before the Dog. And now:

Reflection-dog-exception

Gaah!

The reflection voodoo seems to be making some arbitrary assumptions regarding types based on the first element in the enumerable or some such. You could probably tease out the details using Reflector and coffee, but there’s no point. It’s just broken; I don’t care exactly how. What we need is a simple and predicatable workaround.

Workaround

You can mitigate the problem (aka complicate your program in order to work around a broken framework) by using a wrapper type that always stays the same. That way, the type of the instances handed out by the IEnumerable stays nice and homogenous, just the way DataGrid likes it. Inside the wrapper, you delegate to whatever ICanine you want:


class DataBindingCanineWrapper : ICanine
{
private readonly ICanine _;
public DataBindingCanineWrapper(ICanine canine) {
_ = canine;
}
public string Bark { get { return _.Bark; } }
}

This effectively replaces the original IEnumerable<ICanine> containing the bare Chihuahua and Dog with one that contains only wrapper canines. So data binding should work. And it does:

Wrapped-chihuahua

Notice that we got the Chihuahua Arff!ing as the first grid element.

You could generate such wrappers on the fly, using reflection. In fact, you can download and use something called a “defensive datasource“. Turns out I’m not the only one who’s been bitten and annoyed by this issue.

Peace, love and understanding

Why is DataGrid broken? Well, if you crack open BaseDataList, a base class for both DataGrid and ListBox, you’ll find that the DataSource property assumes that you’re passing it an IEnumerable. No T, just a plain ol’ .NET 1.1-style untyped IEnumerable. So basically, it’s just a series of arbitrary stuff, the type of which could be anything. You could stuff apples and oranges in there, no problem. Now recall this result:

Bark-grid-dogs

See the Bark header? That’s the name of the property shared by Dog and Chihuahua. This is DataGrid auto-generating columns based on the properties of the objects you pass it for data binding. It’s sort of cool, even though it’s broken. Of course, the DataGrid couldn’t pull that trick off without knowing something about the types of the instances in the IEnumerable. In fact, it absolutely needs to know that all instances share the properties that it’s going to display. If you put instances of both Apple and Orange into your IEnumerable, what would you expect to see? You need some commonality between the types, or the whole premise of DataGrid just falls apart.

Of course, an IEnumerable<T> would give you what you need: a common type T for the DataGrid to work with. But DataGrid is stuck with an IEnumerable for its data source and has to make do, somehow. One solution would be to build an inheritance tree for all the elements in the IEnumerable and pick the root type, the least common denominator so to speak. But I imagine that would be costly. Instead, DataGrid looks at the type of the first element, and assumes that the rest will be just like it (or a subclass). Weird, arbitrary, yet at least not completely irrational.

ListBox revisited

Now, given that ListBox also expects an untyped IEnumerable, how come polymorphism seems to work in that case?

Consider three unrelated classes, Huey, Dewey and Louie. We’ll make them singletons since there can only be one of each. More importantly, they all inherit directly from System.Object; there’s nothing else linking them together (no IDuck interface, no Duck base class). Coincidentally, though, they each sport a QuacksLike property.

Here’s the code for Huey:


class Huey
{
private Huey() { }
private static readonly Huey _instance = new Huey();
public static Huey Instance { get { return _instance; } }
public string QuacksLike { get { return "Huey."; } }
}

view raw

Huey.cs

hosted with ❤ by GitHub

As you can imagine, the declarations for Dewey and Louie are remarkably similar.

Let’s toss all three into an IEnumerable and see what happens:


_box.DataSource = new ArrayList { Huey.Instance, Dewey.Instance, Louie.Instance };
_box.DataBind();

The result is this:

Ducks-listbox

Isn’t that something? It’s not really polymorphic at all! Instead, it turns out that ListBox supports duck typing. As long as the object has a public property matching the DataTextField for the ListBox, the actual type is irrelevant. The property’s type is irrelevant too. We could change Dewey‘s implementation of QuacksLike like this, and it will still work:


public Quacker QuacksLike { get { return new Quacker(); } }

view raw

QuacksLike.cs

hosted with ❤ by GitHub

Quacker could be anything, really. Here’s a possibility:


public class Quacker
{
public override string ToString()
{
return "Any ol' duck.";
}
}

view raw

Quacker.cs

hosted with ❤ by GitHub

Now we get this:

Any-old-duck

Of course, if we were to replace Dewey with, say, an Apple, we’d be in trouble (unless it happens to have a public QuacksLike property, but that seems unlikely):

Exception-apple-quacks

No duck typing without quacking, that’s what I always say!

Conclusion

So polymorphism is not actually supported by either control. It’s just that it’s more likely that you’ll notice when you use a DataGrid than a ListBox. Fun!