Tuesday, June 28, 2011

When to use dynamic vs pure reflection?

First of all, a reflection on reflection. Reflection is not a black magic, to know it you don't need to face the mirror and summon some dark forces, but somehow this a bit advance programming is making some feel proud and boasting to peers if they grok reflection, thinking others don't. There's nothing rocket science about reflection. Reflection function names and property names are very intuitive on .NET, you will hardly need documentation. What one need is a due diligence and a bit of googling-fu and asking questions on stackoverflow if one cannot easily infer the right method and property names.


Now back to regular programming. Given this, using pure reflection:

// List all properties of a model
foreach (PropertyInfo p in modelSourceType.GetProperties())
{ 
 // If the property is collection, list all the ID of each collection's item
 if (p.PropertyType.IsGenericType &&  typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
 {  
  object list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
  foreach (var x in (IEnumerable)list)
  {
   object objValue = x.GetType().InvokeMember("ID", BindingFlags.GetProperty, null, x, new object[] { });
   System.Windows.Forms.MessageBox.Show(objValue.ToString());
  } 
 }//if
}

And this, using C# 4's dynamic capability:

// List all properties of a model
foreach (PropertyInfo p in modelSourceType.GetProperties())
{ 
 // If the property is collection, list all the ID of each collection's item
 if (p.PropertyType.IsGenericType &&  typeof(IEnumerable).IsAssignableFrom(p.PropertyType))
 {
  dynamic list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
  foreach (var x in list)
  {
   System.Windows.Forms.MessageBox.Show(x.ID.ToString());
  }
 }//if
}

Which one would you use? I would choose the second code on two conditions, if I'm sure on certain terms that the environment to deploy on will allow to install .NET 4 runtime, and also sure that the certain property (e.g. ID) always exists; the pure reflection is very tedious to code. Make a third condition for choosing the second code, if there's .NET 5 already, no one will sneer at the .NET 4-specific code, second code will have the illusion of backward-compatibility if .NET 5 is out already :p

Some look at latest-version-specific code with disdain ;-)


And oh, it won't hurt to embed the if statement on array's extension method:

foreach( PropertyInfo p in 
 modelSourceType.GetProperties().Where( x => x.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(x.PropertyType)) )
{
 dynamic list = modelSourceType.InvokeMember(p.Name, BindingFlags.GetProperty, null, modelSource, new object[] { });
 foreach (var x in list)
 {
  System.Windows.Forms.MessageBox.Show(x.ID.ToString());
 } 
}

No comments:

Post a Comment