Friday, 10 September 2010

Pseudo-Template Meta-Programming in C# - Part 2

Following on from a taster that I posted before: http://lordzoltan.blogspot.com/2010/09/pseudo-template-meta-programming-in-c.html, here goes with the next piece.

Firstly, the design I'm showing here can be applied to any reflection scenario - I've deployed it in various guises, including for storing meta-data about methods in a class, properties, and even for compiling dynamic methods that provide late-bound functions.  The primary reason why this design, I feel, is particularly useful is that you're making the .Net type engine do all the hard work of storing all this meta-data for you.

I'll go through this by looking at a really simple scenario:

You want to write a system whereby you can reflect properties of a type that a developer writes in order to provide some form of functionality.  Let us say that you want to write a dictionary state-bag wrapper, where a property is wrapped around an internal dictionary of values.  What you want is to have a code-generation friendly way for developers to add such properties to their class with the minimum of fuss.  So, retrieving a property becomes as simple as:

  1. public string SomeProperty
  2. {
  3.     get { return base.GetValue("SomeProperty"); }
  4. }

You don't necessarily want to have the names in the state bag to be the same as the names of the properties, so you need to be able to allow the developer to specify, with the minimum of fuss, what the backer for the property is actually called.

The perfect solution to this is an attribute:

  1. [AttributeUsage(AttributeTargets.Property)]
  2. public class DictionaryPropertyAttribute : Attribute
  3. {
  4.     public string Name { get; set; }
  5. }

Now we can use the attribute as follows (now making a class that we can use later):

  1. public class MyClass
  2. {
  3.     [DictionaryProperty(Name = "PROP_SomeProperty")]
  4.     public string SomeProperty
  5.     {
  6.         get { return base.SetValue("SomeProperty"); }
  7.     }
  8. }

So far so good, but we need a base class to be called.  What we're going to do here is to produce two levels of abstraction: an interface and a base class that we can inherit from.  The base class will implement the interface to provide a simple implementation of a dictionary.  Other implementations could wrap around a data row, ASP.Net ViewState or SessionState and so on.

  1. public interface IDictionaryProps
  2. {
  3.     void SetValue(string name, string value);
  4.     string GetValue(string name);
  5. }

For simplicity's sake we'll say that an implementation of GetValue must return null if a value with the supplied name doesn't exist.  And SetValue should quietly overwrite existing values, while adding new ones.

Our base class, then, looks like this:

  1. public class DictionaryPropertyClass :
  2.     Dictionary<string, string>, IDictionaryProps
  3. {
  4.     public void SetValue(string name, string value)
  5.     {
  6.         this[name] = value;
  7.     }
  8.     public string GetValue(string name)
  9.     {
  10.         string toreturn = null;
  11.         this.TryGetValue(name, out toreturn);
  12.         return toreturn;
  13.     }
  14. }

And that's it, now we can write the outer class, with a couple of minor adjustments, for the wrapped property that I outlined first, so that it inherits from DictionaryPropertyClass.

But wait, what about this mapping business?  Well, that's where we enter the realm of static generics.

For anyone still getting to grips with generic types, they are basically classes with type parameters - unlike C++ templates, however, which are built at compile time in a template-style, the generic class itself (without any type parameters) is a type in its own right - except it cannot be used to create an instance.

TIP: For anyone already doing run-time wizardry with generics - try typeof(MyGeneric<>) - it returns a reference to the generic type rather than an instance of the generic type.  If your generic has multiple parameters, then you simply include a comma for each additional parameter.  typeof(MyGeneric<,,>), for example, returns a reference to the System.Type of a generic that takes three type parameters.

What we're going to do is to create a static generic class (i.e. we never actually create an instance of it) which is going to act as a container for the reflected property information for any type:

  1. public static class DictionaryClassMetaData<T>
  2.     where T : class, IDictionaryProps
  3. {
  4.     //stores the mappings for properties to dictionary keys for T
  5.     private static Dictionary<string, string> _mappings;
  6.  
  7.     //obtains the mapping for a particular property by its name.  Caution,
  8.     //this is case-sensitive of course (use
  9.     //StringComparer.CurrentCultureIgnoreCase  in the constructor for
  10.     //_mappings to avoid this problem if case-sensitivity isn't required).
  11.     public static string GetKey(string propertyname)
  12.     {
  13.         if (_mappings == null)
  14.             return null;
  15.         string toreturn = null;
  16.         _mappings.TryGetValue(propertyname, out toreturn);
  17.         return toreturn;
  18.     }
  19.  
  20.     //static constructor - a lot of debate about these - mainly because of
  21.     //the dreaded TypeInitializationException when the constructor raises
  22.     //an uncaught exception, but if you are careful with your boot-strap code
  23.     //(and religious with try/catch blocks where necessary) you don't have
  24.     //anything to worry about.
  25.     static DictionaryClassMetaData()
  26.     {
  27.         BuildPropertyMap();
  28.     }
  29.  
  30.     //the method that does all the work
  31.     private static void BuildPropertyMap()
  32.     {
  33.         //get the property list for T
  34.         //note the use of System.Linq here and a lambda expression that filters
  35.         //the PropertyInfo objects returned from the GetProperties call so that
  36.         //we only get those properties which have our DictionaryPropertyAttribute
  37.         //note also the use of typeof(T) - allows us to reflect on the T that
  38.         //is fed into the generic type parameter of the static class.
  39.         //finally, note the use of the FlattenHierarchy binding flags - this
  40.         //means that our T can inherit from other types that also declare mapped
  41.         //properties and still be able to get the entire mapping for the whole type.
  42.         IEnumerable<PropertyInfo> props = typeof(T).GetProperties(
  43.              BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy).Where(
  44.                                     pinfo => pinfo.IsDefined(typeof(DictionaryPropertyAttribute), true));
  45.         Dictionary<string, string> tocreate = new Dictionary<string, string>();
  46.         DictionaryPropertyAttribute attr = null;
  47.         //now to build our internal dictionary, if any properties were found
  48.         if (props == null)
  49.             return;
  50.         foreach (PropertyInfo pinfo in props)
  51.         {
  52.             attr = (DictionaryPropertyAttribute)pinfo.GetCustomAttributes(
  53.                 typeof(DictionaryPropertyAttribute), true)[0];
  54.             //make sure the name is unique.  If so, add it. If not, then some form of
  55.             //error reporting should be performed.
  56.             //a good implementation should have a structure within this static type
  57.             //that can be used to obtain errors instead of
  58.             //throwing exceptions
  59.             if (tocreate.ContainsKey(attr.Name) == false)
  60.                 tocreate.Add(pinfo.Name, attr.Name);   
  61.         }
  62.         //if any properties found, set the dictionary, otherwise don't do anything
  63.         if (tocreate.Count != 0)
  64.             _mappings = tocreate;
  65.     }
  66. }

Believe it or not, that's basically it.  From outside of our class MyClass, we can now interrogate property mappings with the following line of code:

  1. string valuekey = DictionaryClassMetaData<MyClass>.GetKey("SomeProperty");

The first time a call like this is made, the .Net runtime will fire the static constructor for DictionaryClassMetaData<MyClass> (remember it's not a proper type until it's actually got a generic parameter in it!), after which it calls the GetKey method.  After that initial call, however, it knows that it doesn't need to call it again, so it just fires the method.  What's more, the .Net runtime ensures thead safety for that call, too, so you don't have to worry about locking anything in a multithreaded environment.

How does this help us with the initial plan?  At the moment, we could reimplement our SomeProperty property in MyClass as follows (only the get accessor code is listed now):

  1. return GetValue(DictionaryClassMetaData<MyClass>.GetKey("SomeProperty"));

Hmmm, smelly isn't it...  What's more - the developer implementing their class needs to know about the meta class - which is no good.

This is where I admit that I've led us down a blind alley - the truth is that the original idea of using base.Foo(bar) as a methodology isn't going to cut it.  Although, as you'll see in a minute, we could implement it that way, there is a better way that we can do it.  Generic extension methods:

  1. public static class IDictionaryPropsExtensions
  2. {
  3.    public static string GetMappedValue<T>(this T instance, string propertyname)
  4.          where T:class,IDictionaryProps
  5.    {
  6.       string datakey = DictionaryClassMetaData<T>.GetKey(propertyname);
  7.       if(datakey == null)
  8.          return null;
  9.       return instance.GetValue(datakey);
  10.    }
  11. }

Now, we can rewrite our implementation of MyClass' SomeProperty as follows (this time, I'll include the full code):

  1. public class MyClass : DictionaryPropertyClass
  2. {
  3.     [DictionaryPropertyAttribute(Name = "PROP_SomeProperty")]
  4.     public string SomeProperty
  5.     {
  6.         get { return this.GetMappedValue("SomeProperty"); }
  7.     }
  8. }

Note how the implementation now uses 'this' directly.  This is a strange feature of extension methods: when inside class scope, you will not see extension methods defined for that type unless you explicitly use 'this' - this is because without the 'this', the intellisense (and presumably the compiler) has no way of knowing that you actually mean 'this'.  This is different from instance members - because they are within scope at the point where you are writing the code (when inside a class definition), therefore they are implicitly available.

We're also using the 'this' as the type parameter for our GetMappedValue extension method.  If you were to breakpoint the extension method and do a get on the property, you will see that 'T' has been implicitly fed into it as MyClass.  This is how we are then able to invoke the static meta class without any real effort whatsoever.

And finally...

Now that you have a static meta class that you can invoke in a single line of code, you can also do it with reflection.  Consider this line of extremely generic code, which could be thought of as being similar to how the databound controls in Windows Forms, WPF and ASP.Net get hold of values when using the 'DataTextField' and 'DataValueField' properties:

  1. public string GetObjectPropertyValue(IDictionaryProps instance, string propertyname)
  2. {
  3. }

So now we're faced with a slight problem - we can't talk directly to the meta data class, because we don't have a T to work with.  If only we could dynamically invoke the meta class...  Hopefully, if you didn't already know it, you have probably guessed that we can.  This time we're using dynamic generics - and this is where my little tip earlier on of using typeof(SomeGeneric<>) comes in really handy:

  1. public string GetObjectPropertyValue(IDictionaryProps instance, string propertyname)
  2. {
  3.     
  4.     Type t = instance.GetType();
  5.     
  6.     Type tmeta = typeof(DictionaryClassMetaData<>).MakeGenericType(new Type[] { t });
  7.     
  8.     return (string)tmeta.InvokeMember("GetKey",
  9.             System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
  10.             null, null, new object[] { propertyname });
  11. }

An interesting note about this code - even when you access a static class via reflection in this way, .Net will still maintain it's rule of firing the static constructor just once.  Also, I'll wager that the speed with which it can obtain the type instance after the initial call is pretty good.

You can (and I have) cache the method for future use in a Delegate stored within the instance (think 'Delegate.MakeDelegate(typeof(Func<string, string>), reflectedmethod);') - this speeds up future access a great deal, because the JIT can optimize away a lot of the method-jumping.

There are some truly crazy things I've done with this model and I might blog about them in the future when I get a chance - in the meantime I hope this provides satisfaction for your coding needs!

Pseudo-Template Meta-Programming in C#

Not full details here, but I'm writing this post as part-memo to myself, but also in the hope that one or two of you might make a mental bookmark to keep checking back.

In the course of my most recent project, which involve classes which wrap a common data storage mechanism (a bit like DataRows) I encountered a problem which was best solved with a solution called (coining a phrase) 'self-aware' properties.  Assuming all the storage access code is provided in a common base, and using attributes to define the string name of the 'column' (to continue the DataRow analogy) to which a property is mapped:

class X
{
  [MappedProperty("actualvaluename")]

  public string SomeValue
  {
     get
     {
        return base.GetPropertyValue("SomeValue");
     }

  }

}

So far so rudimentary.  However, I wanted my framework to be able to support inheritance, so that a class inheriting from another one not only could inherit it's properties, but also so it could actually override the mappings for a property defined by a base, just by using the same attribute.

Also, what I didn't want to have to do was:

a) Store mapping information in every instance of such a class (to weighty)
b) Write some behemoth registry which keeps track of all the mappings (initialisation problems, potential threading issues, not to mention a nightmare to extend and maintain)

The solution that I have produced takes a few ideas from the ideas laid out by C++ Template Meta-Programming (read this book if you want to know more: http://www.amazon.co.uk/Template-Metaprogramming-Concepts-Techniques-Beyond/dp/0321227255), but of course it all happens at run time - because Templates in C++ are not the same as C# Generics.  It takes advantage of an immensely powerful feature of Extension Methods - generic extension methods (think public static void Foo<T>(this T instance, ...) ),  as well dynamic Generic class instantiation using reflection to achieve the generic recursion required to build the data for each level in the class hierarchy.

All it took was a common base (with practically no methods), a static generic class plus some extension methods - and the C# type engine does the rest for you.

In a future post I will lay out the design, but for now I've run out of time (it's Fathers' day - which as many fathers will know doesn't necessarily mean that Father gets to choose what he does!)