Monthly Archives: February 2015

Dynamically extending an object’s properties using TypeDescriptor

The title of this post is slightly misleading in that what I’m really aiming to do is to “appear” to dynamically add properties to an object at runtime, which can then be discover-able by calls to the TypeDescriptor GetProperties method.

What’s the use case ?

The most obvious use for this “technique” is in UI programming whereby you might have an object that either you want to extend to “appear” to have more properties than it really has, or a more likely scenario is where an object has an array of values which you want it to appear as if the items were properties on the object. For example

public class MyObject
{
   public string Name { get; set; }
   public int[] Values { get; set; }
}

We might want this appear as if the Values are actually properties, named P1 to Pn. The is particularly useful when data binding to a Grid control of some sort, so wanting to see the Name and Values as columns in the grid.

Let’s look at how we achieve this…

Eh ? Can I see some code ?

The above use case is an actual one we have on the project I’m working on, but let’s do something a lot simpler to demonstrate the concepts. Let’s instead create an object with three properties and simply dynamically add a fourth property, the class looks like this

public class ThreeColumns
{
   public string One { get; set; }
   public string Two { get; set; }
   public string Three { get; set; }
}

I’ll now demonstrate the code that (when implemented) we’ll use to create an add a fourth property before looking at the actual code that achieves this

// this line would tend to be a class instance variable to ensure the dynamic propetries
// are not GC'd unexpectedly
DynamicPropertyManager<ThreeColumns> propertyManager;

propertyManager = new DynamicPropertyManager<ThreeColumns>();
propertyManager.Properties.Add(
   DynamicPropertyManager<ThreeColumns>.CreateProperty<ThreeColumns, string>(
      "Four",
      t => GetTheValueForFourFromSomewhere(),
      null
));

So the idea is that we’ll aim to create a property manager class which then allows us to add properties to the type, ThreeColumns – but remember these added properties will only be visible by code using the TypeDescriptor to get the list of properties from the object.

If we now created a list of ThreeColumn objects and databind to the DataSource of a grid (such as the Infragistics UltraGrid or XamDataGrid) it would show the four columns for the three real properties and the dynamically created one.

Implementation

Alright we’ve seen the “end game”, let’s now look at how we’re going to create the property manager which will be used to maintain and give access to an implementation of a TypeDescriptionProvider. The property manager looks like this

public class DynamicPropertyManager<TTarget> : IDisposable
{
   private readonly DynamicTypeDescriptionProvider provider;
   private readonly TTarget target;

   public DynamicPropertyManager()
   {
      Type type = typeof (TTarget);

      provider = new DynamicTypeDescriptionProvider(type);
      TypeDescriptor.AddProvider(provider, type);
   }

   public DynamicPropertyManager(TTarget target)
   {
      this.target = target;

      provider = new DynamicTypeDescriptionProvider(typeof(TTarget));
      TypeDescriptor.AddProvider(provider, target);
   }

   public IList<PropertyDescriptor> Properties
   {
      get { return provider.Properties; }
   }

   public void Dispose()
   {
      if (ReferenceEquals(target, null))
      {
         TypeDescriptor.RemoveProvider(provider, typeof(TTarget));
      }
      else
      {
         TypeDescriptor.RemoveProvider(provider, target);
      }
   }

   public static DynamicPropertyDescriptor<TTargetType, TPropertyType> 
      CreateProperty<TTargetType, TPropertyType>(
          string displayName, 
          Func<TTargetType, TPropertyType> getter, 
          Action<TTargetType, TPropertyType> setter, 
          Attribute[] attributes)
   {
      return new DynamicPropertyDescriptor<TTargetType, TPropertyType>(
         displayName, getter, setter, attributes);
   }

   public static DynamicPropertyDescriptor<TTargetType, TPropertyType> 
      CreateProperty<TTargetType, TPropertyType>(
         string displayName, 
         Func<TTargetType, TPropertyType> getHandler, 
         Attribute[] attributes)
   {
      return new DynamicPropertyDescriptor<TTargetType, TPropertyType>(
         displayName, getHandler, (t, p) => { }, attributes);
   }
}

In the above code you’ll notice we can create our dynamic properties on both a type and an instance of a type. Beware, not all UI controls will query for the properties on an instance, but instead will just get those on the type.

So as mentioned the property manager basically manages the lifetime of our TypeDescriptionProvider implementation. So let’s take a look at that code now

public class DynamicTypeDescriptionProvider : TypeDescriptionProvider
{
   private readonly TypeDescriptionProvider provider;
   private readonly List<PropertyDescriptor> properties = new List<PropertyDescriptor>();

   public DynamicTypeDescriptionProvider(Type type)
   {
      provider = TypeDescriptor.GetProvider(type);
   }

   public IList<PropertyDescriptor> Properties
   {
      get { return properties; }
   }

   public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
   {
      return new DynamicCustomTypeDescriptor(
         this, provider.GetTypeDescriptor(objectType, instance));
   }

   private class DynamicCustomTypeDescriptor : CustomTypeDescriptor
   {
      private readonly DynamicTypeDescriptionProvider provider;

      public DynamicCustomTypeDescriptor(DynamicTypeDescriptionProvider provider, 
         ICustomTypeDescriptor descriptor)
            : base(descriptor)
      {
         this.provider = provider;
      }

      public override PropertyDescriptorCollection GetProperties()
      {
         return GetProperties(null);
      }

      public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
      {
         var properties = new PropertyDescriptorCollection(null);

         foreach (PropertyDescriptor property in base.GetProperties(attributes))
         {
            properties.Add(property);
         }

         foreach (PropertyDescriptor property in provider.Properties)
         {
            properties.Add(property);
         }
         return properties;
      }
   }
}

Note: In the inner class DynamicCustomTypeDescriptor we simply append our dynamic properties to the existing ones when creating the PropertyDescriptorCollection however we could replace/merge properties with the existing object’s. So for example replace/intercept an existing property. Also I’ve made the code as simple as possible, but it’s most likely you’d want to look to cache the properties when the PropertyDescriptorCollection is created to save having to get them every time.

So the purpose of the DynamicTypeDescriptionProvider is to basically build our property list and then intercept and handle calls to the GetProperties methods.

Finally, we want a way to create our new properties (via the CreateProperty methods on the DynamicPropertyManager, so now we need to implement our property descriptors

public class DynamicPropertyDescriptor<TTarget, TProperty> : PropertyDescriptor
{
   private readonly Func<TTarget, TProperty> getter;
   private readonly Action<TTarget, TProperty> setter;
   private readonly string propertyName;

   public DynamicPropertyDescriptor(
      string propertyName, 
      Func<TTarget, TProperty> getter, 
      Action<TTarget, TProperty> setter, 
      Attribute[] attributes) 
         : base(propertyName, attributes ?? new Attribute[] { })
   {
      this.setter = setter;
      this.getter = getter;
      this.propertyName = propertyName;
   }

   public override bool Equals(object obj)
   {
      var o = obj as DynamicPropertyDescriptor<TTarget, TProperty>;
      return o != null && o.propertyName.Equals(propertyName);
   }

   public override int GetHashCode()
   {
      return propertyName.GetHashCode();
   }

   public override bool CanResetValue(object component)
   {
      return true;
   }

   public override Type ComponentType
   {
      get { return typeof (TTarget); }
   }

   public override object GetValue(object component)
   {
      return getter((TTarget)component);
   }

   public override bool IsReadOnly
   {
      get { return setter == null; }
   }

   public override Type PropertyType
   {
      get { return typeof(TProperty); }
   }

   public override void ResetValue(object component)
   {
   }

   public override void SetValue(object component, object value)
   {
      setter((TTarget) component, (TProperty) value);
   }

   public override bool ShouldSerializeValue(object component)
   {
      return true;
   }
}

Much of this code is just creates default methods for the abstract class PropertyDescriptor, but as you can see the GetValue and SetValue call our interceptors which we registered with the property manager.

That’s basically that. So now anything calling TypeDescriptor.GetProperties will see our new properties (and their attributes) and interact with those properties through our inteceptor methods.

If you recall the code for creating the property manager we can use the following to confirm that, indeed TypeDescriptor.GetProperties see’s our ThreeColumns object as having four properties

static void Main(string[] args)
{
   DynamicPropertyManager<ThreeColumns> propertyManager;

   propertyManager = new DynamicPropertyManager<ThreeColumns>();
   propertyManager.Properties.Add(
      DynamicPropertyManager<ThreeColumns>.CreateProperty<ThreeColumns, string>(
         "Four",
         t => "Four",
         null
      ));

   var p = TypeDescriptor.GetProperties(typeof (ThreeColumns));
   Console.WriteLine(p.Count); // outputs 4 instead of the 3 real properties
}

Mutual recursion in F#

One of the annoyances of F#, well it is when you come from C# (or the likes), is that to use a function or type, the function or type needs to have been declared before it’s used. Obviously this is a problem if a type references another type which itself references the first type – but ofcourse they F# guys have a way to handle this and it’s called mutual type recursion.

Let’s look at an example of what I’m talking about and at the solution

[<Measure>
type g = 
   static member toKilograms value : float<g> = value / 1000.0<g/kg>
and [<Measure> kg = 
   static member toGrams value : float<kg> = value * 1000.0<g/kg>

The above is taken from my previous post on units of measure.

So in the above code we have type g returning a unit of measure type kg and type kg returns a unit of measure type g. Obviously g cannot use kg as it’s not declared before type g, but it can in the above example by using the and keyword. This can be thought of, as telling the compiler to wait until it’s read all the “chained” types in before evaluating them.

The same technique is used for creating recursive functions which might call other functions which might call the previous function, i.e. circular function calls.

Here’s some code taken from Microsoft’s MSDN site (referenced below) as this is a better example than any I’ve come up with to demonstrate this

let rec Even x =
   if x = 0 then true 
   else Odd (x - 1)
and Odd x =
   if x = 1 then true 
   else Even (x - 1)

So in this code we can see that the function Even is marked as rec so it’s recursive, it may call the function Odd which in turn may call function Even. Again we chain these functions together using the and keyword.

References

Mutually Recursive Functions
Mutually Recursive Types

More Units of Measure

In a previous post I looked at the unit of measure feature of F#. Now it’s time to revisit the topic.

So as a refresher, we can define a unit of measure in the following manner

[<Measure>]
type kg

and we use the unit of measure thus

let weight = 75<kg>

Now it’s important to note that the unit of measure feature only exists at compile time. At runtime there’s no concept of the unit of measure, i.e. we cannot use reflection or anything else to see what the unit used was as it no longer exists. However at compile time the code will not build if we try and use a value with a unit of measure on which is not compatible with another unit of measure.

But there’s more we can do with a unit of measure which makes them even more useful. We can supply a unit of measure with static member functions, for example

[<Measure>
type g = 
   static member toKilograms value : float<g> = value / 1000.0<g/kg>
and [<Measure> kg = 
   static member toGrams value : float<kg> = value * 1000.0<g/kg>

In the example above we use a mutually recursive type (using the and syntax). This allows the g type to use the kg type and vice versa.

With this code we can now write

let kilograms = g.toKilograms 123<g>

The result of this will assign the value kilograms with the result of the toKilograms function as well as setting it’s unit of measure to kg.

Whilst assigning a unit of measure to a numerical value is simple enough, to apply it to an existing value requires the use of an F# core function, from the LanguagePrimitives module.

This code creates a value with a unit of measure

[<Measure>] 
type g = 
    static member create(value : float) = LanguagePrimitives.FloatWithMeasure<g> value

So in the above code we might pass in a value and using the FloatWithMeasure function we apply the g unit of measure

let weight = 123
let weightInGrams = g.create weight

The weightInGrams value will now have the g unit of measure applied to it.

Randomly generating test data using FsCheck

My latest small project is to write a bunch of conversion functions in F#. Basically I want to convert things like, weights from kg to stones. Metres to feet and so on.

I wrote a couple of tests to ensure that the conversions were as expected, but ofcourse with such a set of functions and the wide range of values one might pass to them, my tests simply confirmed a couple of values were correct. It’d be nice to feel like I could say this function is valid for all values within the range x to y.

This is where FsCheck can help.

To use FsCheck just use nuget and search for FsCheck, I also use XUnit so chose FsCheck with XUnit support.

With FsCheck we create properties which define a valid state for a test, so for example if I have a function toMillimetres and another toKilometres, then we can expect that for every value entered into toMillimetres the function toKilometres will return the original value.

This can therefore be described as a property.

At this point we also need to beware that if the calculations involve floating point numbers we may not get back exactly the value we entered, so we’d use something like FsUnit to add a “tolerance” to the formula, i.e. it’s within 0.1 of the expected answer.

Let’s look at some code

[<Property>]
let ``From kilometre to millimetre and back`` () =
   let property value = 
      let millimetres = km.toMillimetres (km.create value)
      let kilometres = mm.toKilometres millimetres

      kilometres
      |> should (equalWithin 0.1) value

   Check.QuickThrowOnFailure (testRange property)

So I’ve created an FsCheck property test named From kilometre to millimetre and back the idea being that (as previously stated) we can put a value into the toMillimetres function then put the result into the toKilometres function and expect (within a tolerance of 0.1) the value to be the same as the resultant kilometres.

The function Check.QuickThrowOnFailure takes our property and in this case, because I wanted to limit the range of the testing, the property goes through the function testRange (which is nothing very exciting) but I’ve listed it below for completeness

let testRange f value =
   let inRange v = (v > -1E+10) && (v < 1E+10)
   inRange value ==> lazy (f value)

The above code simple takes a function f (the property function from the test) and is supplied a value via FsCheck. We then simply ensure the value is within the range -1E+10 to 1E+10 by calling the inRange inner function.

Now when we run this property via FsCheck it will pass multiple values into the property function within the range we’ve defined and runs the unit test.

Note: In the property code I’m using FsCheck with XUnit and FsUnit with Xunit.