Using C# dynamic to call static members

By now, you’ve probably heard that C# 4.0 is adding support for the dynamic keyword, which introduces some aspects of dynamic languages to C#.  I had not had a chance to really try it, but recently I was reading Bertrand Le Roy’s post on the topic, and was sort of looking for a good opportunity to use it.

Today, I found a scenario which I thought it would work great for, but it turned out not to be supported out of the box!

The scenario is to call static class members using dynamic.  That probably sounds crazy, so let’s look at an example.  Say you have these two classes:

 public class Foo1 {
    public static string TransformString(string s) { return s.ToLower(); }
    public static string MyConstant { get { return "Constant from Foo1"; } }
}

public class Foo2 {
    public static string TransformString(string s) { return s.ToUpper(); }
    public static string MyConstant { get { return "Constant from Foo2"; } }
}

Note that they are unrelated classes, but share some members with the same signature.  In a sense, you could say that they two classes share a duck type signature.

Now here is the problem we’re trying to solve: given a System.Type object of either class (or any other random class that shares those members), how can you call those members?   Concretely, we’re trying to implement this method:

 static void MakeTestCalls(Type type) {
    // Call TransformString("Hello World") on this type

    // Get the MyConstant property on this type
}

How can we implement this method? Ok, we can do it the old fashion way using reflection, e.g.

 static void MakeTestCalls(Type type) {
    Console.WriteLine(type.GetMethod("TransformString").Invoke(null, new object[] { "Hello World" }));
    Console.WriteLine(type.GetProperty("MyConstant").GetValue(null, null));
}

That works, but it’s ugly.  These are the very type of things that dynamic is supposed to improve.  So my first naive attempt was to do this:

 static void MakeTestCalls(Type type) {
    dynamic fooTypeDynamic = type;

    Console.WriteLine(fooTypeDynamic.TransformString("Hello World"));
    Console.WriteLine(fooTypeDynamic.MyConstant);
}

Basically, the theory was that when assigning a System.Type to a dynamic variable, it would let you call static members from it.  I didn’t really expect it to work, but I at least had to try! :)  And sure enough, it didn’t work, blowing up with: “Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.RuntimeType' does not contain a definition for 'TransformString'”.

So I then posted the question on our internal C# list, and got a reply from C# guru Eric Lippert, basically saying that it was a potentially interesting idea but was just not supported in C# 4.0.  Fair enough, this is only the beginning of C# dynamic, and it doesn’t do everything.

But I then went back to Bertrand’s post where he gives a great sample of how you can teach dymamic new tricks by implementing a custom DynamicObject.  And it turned out to be relative simple.  Here is the class I ended up with:

 public class StaticMembersDynamicWrapper : DynamicObject {
    private Type _type;
    public StaticMembersDynamicWrapper(Type type) { _type = type; }

    // Handle static properties
    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        PropertyInfo prop = _type.GetProperty(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);
        if (prop == null) {
            result = null;
            return false;
        }

        result = prop.GetValue(null, null);
        return true;
    }

    // Handle static methods
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
        MethodInfo method = _type.GetMethod(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);
        if (method == null) {
            result = null;
            return false;
        }

        result = method.Invoke(null, args);
        return true;
    }
}

The idea is pretty simple: when the runtime needs to call something, it basically asks you to do it.  It passes you the method (or property) name and the parameters, and you take it from there. And in this case, of course, we’re using reflection.

Once we have that, the real fun starts as we’re now able to call our static members using dynamic!

 static void MakeTestCalls(Type type) {
    dynamic typeDynamic = new StaticMembersDynamicWrapper(type);

    // Call TransformString("Hello World") on this type
    Console.WriteLine(typeDynamic.TransformString("Hello World"));

    // Get the MyConstant property on this type
    Console.WriteLine(typeDynamic.MyConstant);
}

Note how we wrap the type into our custom DynamicObject is order to have the dynamic invocations go through us.

Now you might say that the scenario above where you have two classes with identical static members doesn’t seem like something that would actually occur commonly in real apps.  But once you start bringing in generics, it can actually be more common.  e.g. suppose you have something like:

 public class Table<T> {
    public static IEnumerable<T> Records { get { [return records from database table T] } }
}

The idea is that the class is an abstraction for a database table.  So Table<Product>.Records returns an IEnumerable<Products>, and Table<Category>.Records returns an IEnumerable<Category>.  Now suppose you’re writing some table agnostic code that can work with the data from any table.  You have a System.Type for some Table<T>, and you need to get its Records property.  Even though it seems like it’s the same Records property coming for a base class, the reality is that it’s a completely different property for each T, and C# provides no simple way of making the call.  But with the technique above, you get to access the property with a much simpler syntax than with reflection.

The zipped sample is attached to this post.

DynamicCallsToStaticMembers.zip