Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling a C# method that isn't defined on a dynamic object (aka respond_to/method_missing)

Tags:

dynamic

c#-4.0

Given the new dynamic support in C# 4, is it possible to write a class in such a way that if a method is invoked on an instance and that method is not present, dispatch is passed to another method? This might look something like:

public class Apple : ... {
  // ...

  private ... MethodMissing(string name, ...) {
    if (name == "TurnIntoOrange") {
      // do something
    }
  }
}

dynamic d = new Apple();
d.TurnIntoOrange();       // Not actually defined on Apple; will pass to MethodMissing.

Other languages would call this "method_missing support", under the more general heading of metaprogramming. I'm not sure what C# calls this specifically. But is it possible?

like image 545
Kyle Kaitan Avatar asked Jul 10 '09 16:07

Kyle Kaitan


1 Answers

Absolutely. Either implement IDynamicMetaObjectProvider or derive from DynamicObject for a much simpler route. See the DLR documentation for some good examples.

Here's a quick example of DynamicObject:

using System;
using System.Dynamic;

public class MyDynamic : DynamicObject
{
    public override bool TryInvokeMember
        (InvokeMemberBinder binder,
         object[] args,
         out object result)
    {
        Console.WriteLine("I would have invoked: {0}",
                          binder.Name);
        result = "dummy";
        return true;
    }

    public string NormalMethod()
    {
        Console.WriteLine("In NormalMethod");
        return "normal";
    }
}

class Test
{
    static void Main()
    {
        dynamic d = new MyDynamic();
        Console.WriteLine(d.HelloWorld());
        Console.WriteLine(d.NormalMethod());
    }
}

<plug>

I have a bigger example of DynamicObject in the 2nd edition of C# in Depth but I haven't yet implemented IDyamicMetaObjectProvider. I'll do so before the book's release, but the early access edition only has the DynamicObject example at the moment. Btw, if you buy it today it's half price - use the code twtr0711. I'll edit this answer later on to remove that bit :)

</plug>

like image 158
Jon Skeet Avatar answered Oct 18 '22 21:10

Jon Skeet