Welcome to EMC Consulting Blogs Sign in | Join | Help

Howard van Rooijen's EMC Consulting Blog (2004 - 2010)

This blog has now moved to http://howard.vanrooijen.co.uk/blog - please update your subscriptions if you wish to receive new content.

Reduce PropertyGrid development pain by using LINQ Dynamic Expressions

As I mentioned in my last post I've been working with Microsoft Blueprints, one of the problems I encountered was trying to come up with a generic, reusable way of working with T4 Templates (T4 is the used by Blueprints for all code generation as T4  is now integrated into Visual Studio 2008) to generate the code fragments.

I created a T4TemplateBuilder object that exposes a fluent interface to take the pain out of manipulating T4 Templates:

T4Template template = T4TemplateBuilder
                        .Initialise(context)
                            .SetTemplateFileName("MyT4Template.tt")
                            .SetTargetFileName(@"C:\Temp", "MyFolder\MyGeneratedFile.cs")
                            .SetProperty("MyProperty", "MyValue")
                            .Transform()
                            .SaveToFile()
                        .Finish();

The T4TemplateBuilder parses (using a simple RegExp) any T4 template to dynamically retrieve a list of properties that need to be passed in. I wanted to provide a simple GUI to allow the user to enter values for the T4 Template properties as part of the Blueprint “unfolding” process. Rather than re-inventing the wheel I decided to try and use the PropertyGrid Control.

The data structure used to hold the T4 Template data within the Blueprints Framework is a generic Dictionary: Dictionary<string, Pair<string, Type>>() and unfortunately if you bind this to the PropertyGrid Control, you get the following:

clip_image002[4]

After doing a bit of research it became quite apparent that although incredibly adaptable, the PropertyGrid control is an absolute pain to work with as you have to create lots of glue code (TypeConverters) to make your objects display correctly.

I started wondering if there was a way to create some dynamic anonymous types using LINQ (after a conversation with Rob Blackwell of AWS on how he implemented LSharp with LINQ Expression Trees). After reading a few articles about Code Generation with LINQ and while waiting for the nose bleed to stop, I stumbled across this article from the mighty ScottGu which talks about Dynamic LINQ. After downloading the sample I realised that I had found the solution to my problem – the Dynamic LINQ Library. This allows you to create dynamic properties and attach them to dynamic classes (which are essentially anonymous types) and then instantiate them.

The dictionary contains entries for the following values:  InstallerType, WixProductId, WiXProductName. In the code below we iterate the dictionary and create DynamicProperties based on the values in the dictionary, attach them to a dynamic class and then instantiate it.

var dynamicProperties = new List<DynamicProperty>();

// Iterate our dictionary and create dynamic properties that match our values.
foreach (KeyValuePair<string, Pair<string, Type>> pair in this.templateProperties)
{
    // i.e. we are creating a new Dynamic Property called "InstallerType"
    // which is of type string.
    dynamicProperties.Add(new DynamicProperty(pair.Key, pair.Value.Second));
}

// Create a dynamic, anonymous type which contains those properties
this.dynamicType = DynamicExpression.CreateClass(dynamicProperties);

// Create an instance of the anonymous type. W00t!
this.dynamicObject = Activator.CreateInstance(this.dynamicType);

This new dynamicObject can now be attached to the PropertyGrid to give the desired experience:

Fill in the values:

Next we have to pull the values back out of the dynamicObject and put them back into the Dictionary so that it can be passed into the T4 Transformation Engine:

var updatedTemplateProperties = new Dictionary<string, Pair<string, Type>>();

foreach (KeyValuePair<string, Pair<string, Type>> pair in this.templateProperties)
{
    string value = (string)this.dynamicType.GetProperty(pair.Key).GetValue(this.propertyGrid.SelectedObject, null);

    updatedTemplateProperties.Add(pair.Key, new Pair<string, Type>(value, pair.Value.Second));
}

this.templateProperties = updatedTemplateProperties;

Then we can display the dictionary object to prove we have the updated values:

clip_image002[10]

I've uploaded a sample application to my CodePlex project.

Published Monday, March 02, 2009 8:28 AM by howard.vanrooijen

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Armin Ortmann said:

Great stuff, really enlightening! Exactly what i need right now and eventually of course elegant means to coax PropertyGrid into displaying exactly what one wants without going totally insane with custom Type- and PropertyDescriptors and truckloads of Attributes.

Guess I just have to take care not to drown my app in dynamically generated types :-)

Thanks again!

Armin

November 12, 2009 4:45 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

This Blog

Syndication

News

This blog has now moved - please visit http://howard.vanrooijen.co.uk/blog for new content!
Add to Live.com
Powered by Community Server (Personal Edition), by Telligent Systems