The Dynamic Duo: ExpandoObject and DynamicObject – Part 2
DISCLAIMER: PLEASE READ THE PERFOMANCE IMPLICATIONS AT THE END OF THIS POST!
The ExpandoObject I was talking about in my last post is actually not too much of a help in most cases meaning I didn’t miss it too much before it was there. There are some special scenarios but that’s about it. A much more interesting beast is DynamicObject. While the ExpandoObject is holding a internal collection of Properties and their values, DynamicObject is providing overrideable methods for member access like getting or setting members, calling methods and more. All calls on this object are channeled into a few methods. Every access to a Property like var name= myDynamicPerson.FirstName; will actually result in a call to the Method bool TryGetMember(GetMemberBinder binder, out object result). From there you can do with it whatever you want. Within the binder parameter is the Property Name, which gives you the member name asked for in the first place. For the above example its value would be “FirstName”. You can then access the Property value via Reflection or Expressions. This is a perfect place to put some code around it, decorating the actual call. The following code shows a simple override for Property getters:
var _Person = new DynamicPerson{ FirstName = "Paulie" };
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _Person.GetProperty(binder.Name).GetValue(_Person, null);
return true;
}
Using binder.Name the value for the requested Property is retrieved and put into the out variable result. The boolean return value indicates wether the call was successful meaning returning false will result into an Exception stating the requested member could not be found on the target object.
Using this approach it gets easy to actually implement single responsibilities like tracing, logging or security into different classes and chain these. Tracing could be done like this for example:
public class DynamicTracer : DynamicObject
{
private readonly DynamicObject decoratedObject;
private ITracer _Tracer = new FakeTracer();
public DynamicTracer(DynamicObject decoratedObject)
{
this.decoratedObject = decoratedObject;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
_Tracer.Trace(string.Format("-> Before member access ({0})", binder.Name));
decoratedObject.TryGetMember(binder, out result);
_Tracer.Trace(string.Format("-> After member access ({0})", binder.Name));
return true;
}
}
It’s just wrapped around the original DynamicObject calling its TryGetMember method with the given Parameters. All that’s needed is the target object (dynamic) which is injected via the constructor and the actual call gets decorated with the tracing calls.
This can be repeated to achieve a real chain of functionality (Handler chain). A simple (and pretty useless) security managing class could look like this:
public class DynamicSecurityManager : DynamicObject
{
private readonly DynamicObject decoratedObject;
public DynamicSecurityManager(DynamicObject decoratedObject)
{
this.decoratedObject = decoratedObject;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
if(binder.Name != "SecureInfo")
{
decoratedObject.TryGetMember(binder, out result);
return true;
}
System.Console.WriteLine("-> The requested info is not for your eyes!!!");
return true;
}
}
You would then instantiate and use it like this:
dynamic person = new DynamicSecurityManager(
new DynamicTracer(
new DynamicPerson(
new Person { FirstName = "Paulie" })));
var name = person.FirstName;
What this gives you is the actual object (DynamicPerson) surrounded by a Tracing component surrounded by a security component.
So when should you use this?! Well you shouldn’t forget that all calls will be based on Reflection, going this route. This doesn’t have to be a problem, just be aware of the implications. This means performance will degrade when doing more calls via this technique. This can be adressed with caching the compiled invocation delegates or even better the usage of HyperPropertyDescriptors. To be honest there are better solutions around for most situations, but not all. There is the Castle DynamicProxy as long as all target members are virtual and there’s PostSharp for Aspect Oriented Programming using a post compiler so the resulting code will be executed like it was written that way. Direct invocations, no reflection, no Voodoo…
Still, if you don’t want to introduce third party libs or don’t want to pay for PostSharp (there’s a free community editon available) DynamicObject might be something to try.
Get the sample code from http://dl.dropbox.com/u/13456770/IDevign/IDevign.Dynamic.zip.


