Silverlight Anonymous Type Binding Gotcha

When Silverlight databinding evaluates a binding expression, it does one of two things. If the object it is bound to inherits from FrameworkElement and there is a DependencyProperty matching the binding expression, it uses FrameworkElement.GetValue to retrieve the value [simplified]. If not a FrameworkElement and not a DependencyProperty, Silverlight falls back to using reflection to retrieve the values.

This is problematic if you attempt to data bind to an anonymous type.

In Silverlight, when you attempt to use reflection to retrieve a property value of an object whose Type is not defined in your assembly, a MethodAccessExcepttion is thrown. Go ahead I'll give you a minute to test it.

Or follow along if you want to take my word for it. Create two projects: one Silverlight Application and one Silverlight Class Library. Add a reference to the library from the application. In the library, add the following classes:

   1:  public class Class1 {
   2:      public object GetFoo() {
   3:          return new Foo() {
   4:              Baz = "baz1",
   5:              Bap = "bap1"
   6:          };
   7:      }
   8:   
   9:      public object GetBar() {
  10:          return new Bar() {
  11:              Baz = "baz1",
  12:              Bap = "bap1"
  13:          };
  14:      }
  15:  }
  16:   
  17:  public class Bar {
  18:      public string Baz { get; set; }
  19:      public string Bap { get; set; }
  20:  }
  21:   
  22:  class Foo {
  23:      public string Baz { get; set; }
  24:      public string Bap { get; set; }
  25:  }

Now in the application, add the following code inside App.xaml.cs:

   1:  Class1 c = new Class1();
   2:  var o = c.GetFoo();
   3:  var prop = o.GetType().GetProperty( "Baz" );
   4:  try {
   5:      var value = prop.GetValue( o, null );
   6:  }
   7:  catch( MethodAccessException ex ) {
   8:      System.Diagnostics.Debugger.Break();
   9:  }
  10:   
  11:  o = c.GetBar();
  12:  prop = o.GetType().GetProperty( "Baz" );
  13:  try {
  14:      var value = prop.GetValue( o, null );
  15:  }
  16:  catch( MethodAccessException ex ) {
  17:      System.Diagnostics.Debugger.Break();
  18:  }

Run the application. The debugger will stop inside the first catch on line 8 but not the second on line 17. What this tells us is that you can use reflection to get the value of properties on a public Type defined in another assembly, but not on one that isn't public.

Why is this important? It's important because anonymous Types are defined internal to the assembly that they are used in. Because they are not public, and the data binding framework is not in the same assembly (it's in System.Windows), it will receive an exception when trying to use reflection to get the value of a property from an anonymous type.

To get around this, simply create a "dummy object" (same as a DTO) that is public and has all the public properties you need. Then instead of this format:

   1:  var results = from d in data
   2:                select new {
   3:                    Bar = d.Bar,
   4:                    Baz = d.Baz
   5:                };

You use this format:

   1:  var results = from d in data
   2:                select new Result() {
   3:                    Bar = d.Bar,
   4:                    Baz = d.Baz
   5:                };

 

Post your comment