Using DynamicObject to intercept and marshal property changes

One of the most interesting (and potentially dangerous) new features in C# 4.0 is support for the dynamic type.  It allows certain pieces of your code to bypass the normal compile-time type checking features that we have grown to know and love.  You can use a dynamic object however you want to, and the C# compiler will ignore the members you use on it.  At runtime, if the methods/properties/etc. your code tries to use are not actually present on the object, an exception is thrown.  If they do exist, they will be linked to and invoked dynamically.   This technique is called dynamic dispatch.  What you lose in safety, you gain in flexibility.

In addition to the dynamic keyword there is also support in the .NET Framework 4.0 for creating types that support dynamic dispatch. The System.Dynamic.DynamicObject class allows you to specify how an object performs dynamic dispatch.  You can subclass DynamicObject and override some of its methods, such as TrySetMember and TryGetMember, to perform whatever logic you need to link a dynamic property set or get to a backing store.

Sound pretty cool, right?  That’s what I thought when I first heard about this functionality.  Then I thought, “Why would I ever need to use this?”  I didn’t have an answer to that question, until tonight.  It dawned on me, while trying to read something not related to programming (damn OCD!), that this could be leveraged to implement a simple, reusable means of marshaling property changes to the UI thread.

As you probably know, you cannot get or set a visual element’s properties from any thread except the thread on which it was created.  When the UI thread creates an element, that element thereafter has an affinity to the UI thread’s Dispatcher object.  The only property on an element that you can access from another thread is its Dispatcher property.  Once you have a reference to an element’s Dispatcher, you can use it to dispatch method calls that manipulate the element on the UI thread.

If you work on a lot of UI-level components and controls, like I do, you probably find yourself writing a lot of code that works with Dispatchers just to do something simple like get or set an element’s property.  What a pain!  It turns out that this pain can be somewhat eliminated by making use of DynamicObject and the dynamic keyword.  Here’s a contrived example that shows how…

The code snippet above shows how to use my DynamicElement class.  It acts as a proxy to an element, which intercepts all access to an element’s properties.  This interception allows the DynamicElement to make use of the visual element’s Dispatcher, if necessary.  Here is how the interception works for setting a property:

The TryGetMember implementation is similar to the code seen above.

You can download the source code here.  NOTE: Rename the file extension from .DOC to .ZIP and then decompress it.

15 Responses to Using DynamicObject to intercept and marshal property changes

  1. sacha says:

    A nice example of working with dynamic there Josh

  2. bitbonk says:

    WPF Databinding already marshales propertychanges to the UI Thread. In MVVM databinding is the preferred way to set properties on UI Elements. How often have you actually come across the need to set properties of UI Elements directly in code?

  3. Josh Smith says:

    Yeah, I know that bindings marshal property changes to the UI thread. Not sure why you’d call that the “preferred” way to set properties, though. I’ve worked on plenty of components that need to update UI element properties from background threads.

  4. Hi Josh, cool idea !

    Actually, you could easily make this more generic, by using the SynchronizationContext rather than the Dispatcher (the SynchronizationContext abstracts the synchronization mechanism used by the current application). That way, the same DynamicElement class could be used with all kinds of UI frameworks, not just WPF

  5. Josh Smith says:

    That’s an interesting idea, Thomas. From an implementation perspective, how would I get the correct SyncContext? A thread’s SyncContext.Current can be null, so I’m not sure how I would find the current one, assuming the DynamicElement could be created on any thread.

    Thanks,
    Josh

  6. Hi Josh, so far I’ve never seen a case where SynchronizationContext.Current is null… But I looked at the implementation with Reflector, and it seems that you’re right. Anyway, I’m currently using it in a custom collection, and I didn’t have any problem with yet

  7. Andrew Smith says:

    It’s an interesting idea but I think it may promote bad practices. In your example you are setting 2 UI properties so you are marshalling 2 separate calls to the ui thread. When someone wants to interact with the ui thread it is best if they just marshall one call and do all the ui interaction in a single operation. Not only is that more effecient but it would all happen together. The way the sample is there could be changes that have occurred on the ui thread between the 2 property setters since each one is marshalled synchronously.

    Also you lost compile time type safety as a result so if you accidentally used the wrong type for one of those properties it would crash the app.

  8. Josh Smith says:

    Good point, Andrew. I’m not totally sold on the idea, either. I just thought it was an interesting use of the new dynamic dispatch support in .NET 4. To be honest, the whole idea gives me the creeps. I can only imagine the potential for misuse and abuse it opens up.

    With that said, for a small number of property accesses, it isn’t too much overhead, in my opinion.

  9. Andrew whiddett says:

    Yes Andrew has a great point. Maybe a better way would be to create a transaction context that has a queue of updates and have a commit which processes on the dispatcher thread.

  10. Nice concept Josh… Not sure it is quite perfected yet, but definately a step in the right direction!

    I always feel a little dirty writing code where getting a property directly after setting it doesn’t give the same value back again (I vaguely remember the framework guidelines warning against this and recomending a SetXXX() method instead). Then again, this is the world of multi-threading here so changes in state out of order is par for the course.

    Regarding the comments about type safety. My first thought was something like a T4 template that would create a true proxy class (i.e. a ‘TextBlockProxy’ class) which would act as a statically typed version of your ‘DynamicElement’ class. Lot’s of extra classes created though – and the more I think about it, the less I like this idea.

    For interest, one other place I can think of for using the C# 4.0 dynamic type (and the fact that WPF 4.0 includes binding to dynamic properties) is for binding a UI to a property on a ViewModel that is “dynamic” at run-time. The example I’m thinking of regions in a composite UI, where each region could be bound to a VM property. I really should blog about how I am using this at some point.

    Andy

  11. Josh Smith says:

    Andy Wilkinson,

    I agree that a queued approach to setting properties would lead to strange semantics. I’m not even sure it would work, since you can do boolean assignment as a condition, like:

    if (proxy.IsEnabled = proxy.IsHitTestVisible) { … }

    That sounds like it would be an interesting blog post, Andy.

    Thanks,
    Josh

  12. Duncan says:

    That is a very smooooth idea Josh. Not entirely sold on it however as I think it is usually a good idea to be very aware of thread boundaries… obscuring them so I fear may make it hard to test and even harder to follow.

    I’m very much a fan of clearly separating cross-thread concerns from all others. I like to be able to unit test everything without the interference of threads (not always possible I admit).

    Still, a very interesting idea that I’m sure will ruminate in my head for days.

    As to what else we can use dynamic for… I’m sure a killer idea will arise eventually (re-implementation of ‘Binding’?).

  13. Hi Josh,

    Loved this post. It inspired me to experiment with DynamicObject myself.
    I created a proxy class that exposes the properties of a wrapped object and adds an automatic implementation of INotifyPropertyChanged. Take a look at http://codeflow49.blogspot.com/2010/06/automatic-inotifypropertychanged-with.html

    I think there’s a great potential for other kinds of dynamic proxies that mediate/extend the behaviours of other types, but I suspect many C# programmers are going feel uneasy adjusting to dynamic types.

  14. Ken Jackson says:

    @bitbonk, I thought that you had to modfiy properties that were databound to UI elements on the appropriate UI thread? Is this not the case? I could have swore that I’ve hit that exception before.

%d bloggers like this: