I just stumbled upon this other thing that I don’t think I know: is it possible to dispatch really dynamically through the DLR, from C#? Let me explain.
We know that we can use dynamic in C# 4.0, like so:
dynamic i = 10; // i is now dynamic, but still works like an int: int j = i + 10 // I can call crazy stuff on i, but the compiler doesn't care - // it'll crash at runtime of course i.DoSomethingYouCantReallyDo();
If you haven’t checked out code like this in Reflector, go ahead and do so. You’ll find that the C# compiler generates a rather large amount of code for each “dynamic call site”, which calls into the DLR and instructs it to dispatch the calls (in the case above to the operator + as well as the DoSomethingYouCantReallyDo method) to the objects. The DLR in turn has a number of fallback mechanisms to try, basically the way dispatch happens in the end depends on the type of object you use. Fair enough.
Now, what if I know the name of a method on an object at runtime, but I didn’t know it at design time. Obviously the compiler can’t create clever code for me in that case. Basically, I’d like to do this:
string methodName = "AddValues"; // in reality, retrieve this from somewhere at runtime dynamic o = ... // retrieve dynamic object from somewhere as well // Now call the method with the name 'methodName' on the object o, passing in params x and y o.DispatchDynamically(methodName, x, y);
The method DispatchDynamically in the last line doesn’t exist — at least I don’t think it does! That’s my question, the thing I don’t currently know — is there a method like this somewhere?
I know this is possible when talking to IronPython, for instance. In this case I can use IronPython specific data structures (PythonEngine et al.) to retrieve info on the members that are available etc. I’ve done that, no problem. Of course in Python this is ridiculously easy anyway:
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> foo = "hi there" >>> foo.upper() 'HI THERE' >>> foo.__getattribute__("upper")() 'HI THERE' >>>
The only way that might work — and I haven’t followed up on this in any detail — is to write code similar to that usually created by the compiler, but manually. Looking at Reflector, this will make for an extremely horrible “API”, but I guess it’s possible. Although at the very least I’d have to use stuff out of the System.Runtime.CompilerServices namespace, which seems a bit extreme… but who knows, maybe this is the way? Not intuitive, if it is!
For some odd reason, I can’t currently find a good answer to this problem and I’m just now out of time to keep looking for it. I hope I’m missing something and somebody is going to come forward and tell me what it is.
It’s an odd fact that there are quite a few blog posts out there about how dynamic in C# 4.0 is going to be so great instead of Reflection. Weird, because none of the posts I could find takes a very simple fact into account: I’m going to use Reflection scenarios mostly when I don’t know at design time what it is that I’m going to be invoking at runtime. Surely, that’s a very important point of it. Well. Seems like that is at least as hard with dynamic, if perhaps more performant.