Actual *dynamic* dispatch through the DLR from C#?

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.

3 Comments on Actual *dynamic* dispatch through the DLR from C#?

  1. Hey Oliver,

    Just an FYI, VB.NET has always had intrinsic support for this scenario with the CallByName method. http://msdn.microsoft.com/en-us/library/chsc1tx6(VS.71).aspx

    Module Module1
        Sub Main()
            Dim o As New MyObject
            CallByName(o, "Print", CallType.Method, "Hello CallByName")
        End Sub
    End Module
    Public Class MyObject
        Sub Print(ByVal str As String)
            Console.WriteLine(str)
        End Sub
    End Class
    

    However it is limited to the scenario you describe above, calling a *method* on an object dynamically, the object must be instantiated first. For C# I think you have to fall back on the Reflection APIs to do this, I don’t know of a more elegant way, maybe someone will chime in :-). You can do the same thing as above using reflection:

    Dim mi = o.GetType.GetMethod("Print")
    Dim p() As Object = {"Hello Reflection"}
    mi.Invoke(o, p)
    

    Reflection would also allow you to get the name of the object itself dynamically as well.

    As an aside, in VFP (I know we’re going wayyyy back here) has a very powerful, flexible and dangerous feature called macro substitution (or macro expansion) where you could “expand” a string literal into ANY command. This way you could read commands stored as text in a database and execute them at runtime. (Think dynamic business rules engine)
    http://fox.wikis.com/wc.dll?Wiki~MacroSubstitution

    Cheers!
    -Beth

    Like

  2. Hi Beth, nice to hear from you!

    Thanks for pointing out the Reflection thing – I forgot to mention it, but of course I was trying to do without it 🙂 The idea I had in mind is that my dynamic object may be really dynamic and the DLR could then do its brilliant dispatch thing for flexibility.

    Plus, in some tests I did, DLR dispatch is inexplicably faster than compiled expression trees – I’m not sure whether this is because the DLR is just better optimized than my code (that creates and caches said expression trees), or whether it’s because the compiler plays an important part in all the DLR dispatch tests I can do. My expression tree method is, after all, *really* dynamic (and way faster than Reflection, btw), and as things are, I can’t really tell whether the DLR would be faster if it did what I want it to do 🙂

    Finally, an update: I’ve also looked into the idea I mentioned towards the end of my post, about replicating the code the compiler creates. This is generally possible, but unfortunately the DLR API is quite complex, and it seems very hard to create some meaningful helper functions. Basically quite similar to complex Reflection scenarios…

    Well, this is all very unfortunate. Hopefully the DLR is going to improve lots in these areas!

    Like

  3. Hi Oliver,

    c# Dynamic call cache is an one item cache. Name of function is “static” so Compiler injects the code into dynamic part so it only checks one item ‘the instace’. This type is a static dynamic call(!). Calling dynamic but the function name is static! But if you implement dynamic name call with function name call like Invoke(obj,functionname) with exression trees. you must have a cache of multiple functions. So generating key and cash hit time affects the performance. That why c#4 dynamic call seems faster.

    Compiler injects the code like

    static Action func_DoSomethingYouCantReallyDo;
    if(func_DoSomethingYouCantReallyDo==null)
    {
    //Generate and compile expression tree
    }
    func_DoSomethingYouCantReallyDo(obj);

    Bu c# uses more complex types to invoke. Like callsitecache and binders. You can see it with reflector.

    So this kind of caching is useless in dynamic function name dynamic calls.

    Like

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s