The Imaginative Universal

Studies in Virtual Phenomenology -- @jamesashley

Speaking at DevLink

Our far-flung correspondent from self-promotion land writes:

I received an invitation this past week to speak at DevLink.  I will be presenting on two topics:

The C# 4 Dynamic Objects session will be a longer version of the talk I gave at the MVP Summit in February.  The Advanced Windows Phone 7 talk is one I find I am updating every few weeks as more tools and information about the platform become available.

DevLink is a three day conference being held in Nashville, August 5-7.

Addendum to Dynamic Method Bags

Bill Wagner has an interesting article on MSDN about implementing Dynamic Objects in C# 4: http://msdn.microsoft.com/en-us/library/ee658247.aspx.  He leaves it up to the reader to figure out the right way to implement the class he describes and provides suggestions.  This is a great way to structure a propaedeutic of this sort, as it affords the clever reader an opportunity to dig into the material on her own.

At the same time, it is often helpful to have a key against which to compare one’s own work.  To that end, the full code required to run the sample application described in the article follows.

Here is the code that serves as our test.  Bill Wagner describes an object that inherits from DynamicObject that will run the following code:

    var newType = new MethodBag();
    newType.SetMethod("Write", () => Console.WriteLine("Hello World"));
    newType.SetMethod("Display", (string parm) => Console.WriteLine(parm));
    newType.SetMethod("IsValid", () => true);
    newType.SetMethod("Square", (int num) => num * num);
    newType.SetMethod("Sequence", () => from n in Enumerable.Range(1, 100)
                                        where n % 5 == 2
                                        select n * n);
    dynamic dispatcher = newType;
    dispatcher.Write();
    var result = dispatcher.IsValid();
    Console.WriteLine(result);
    dispatcher.Display("This is a message");
    var result2 = dispatcher.Square(5);
    Console.WriteLine(result2);
    var sequence = dispatcher.Sequence();
    foreach (var num in sequence)
        Console.WriteLine(num);

    Console.ReadLine();

 

Here is an implementation of MethodBag that will fulfill the expectations established above:

internal class MethodBag: DynamicObject
{
    private Dictionary<string, MethodDescription> methods = 
        new Dictionary<string, MethodDescription>();

    #region Method Descriptions

    private abstract class MethodDescription
    {
        internal abstract int NumberOfParameters
        {
            get;
        }
        internal Expression target
        {
            get;
            set;
        }
        internal abstract object Invoke(object[] parms);
    }

    private class ActionDescription: MethodDescription
    {
        internal override int NumberOfParameters
        {
            get { return 0; }
        }
        internal override object Invoke(object[] parms)
        {
            var target2 = target as Expression<Action>;
            target2.Compile().Invoke();
            return null;
        }
    }

    private class ActionDescription<T> : MethodDescription
    {
        internal override int NumberOfParameters
        {
            get { return 1; }
        }
        internal override object Invoke(object[] parms)
        {
            dynamic target2 = target;
            target2.Compile().Invoke(parms[0]);
            return null;
        }
    }

    private class FuncDescription<T> : MethodDescription
    {
        internal override int NumberOfParameters
        {
            get { return 0; }
        }
        internal override object Invoke(object[] parms)
        {
            dynamic target2 = target;
            return target2.Compile().Invoke();
        }
    }

    private class FuncDescription<T,S> : MethodDescription
    {
        internal override int NumberOfParameters
        {
            get { return 1; }
        }
        internal override object Invoke(object[] parms)
        {
            dynamic target2 = target;
            return target2.Compile().Invoke(parms[0]);

        }
    }

    #endregion

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args
        , out object result)
    {
        result = null;
        if (!methods.ContainsKey(binder.Name))
            return false;
        // Described later
        MethodDescription method = methods[binder.Name];
        if (method.NumberOfParameters != args.Length)
            return false;
        result = method.Invoke(args);
        return true;

    }

    #region Set Methods

    public void SetMethod(string name, Expression<Action> lambda)
    {
        var desc = new ActionDescription { target = lambda };
        methods.Add(name, desc);
    }

    public void SetMethod<T>(string name, Expression<Action<T>> lambda)
    {
        var desc = new ActionDescription<T> { target = lambda };
        methods.Add(name, desc);
    }

    public void SetMethod<T>(string name, Expression<Func<T>> lambda)
    {
        var desc = new FuncDescription<T> { target = lambda };
        methods.Add(name, desc);
    }
    
    public void SetMethod<T,S>(string name, Expression<Func<T,S>> lambda)
    {
        var desc = new FuncDescription<T,S> { target = lambda };
        methods.Add(name, desc);
    }

    #endregion
}

 

Your output should look like this:

Hello World
True
This is a message
25
4
49
144
289
484
729
1024
1369
1764
2209
2704
3249
3844
4489
5184
5929
6724
7569
8464
9409

That Wild and Crazy Dynamic Type

I had a mind-blowing weekend playing with the ExpandoObject in C# 4.0.  When an article appeared on MSDN about it prior to the release of Visual Studio 2010 Beta 2, it looked interesting but not particularly useful.  The ExpandoObject appeared to be merely a property bag that was useful in limited circumstances in which the program flow is aware of the properties being added.  The ExpandoObject is, in essence, a property bag (and also a method bag?) that pretends to be a real type.  With the Beta 1, I tried to bind a WPF Window to it and was quickly disappointed to find that WPF just treated it as a dictionary (which is what it really is) rather than as the typed class it is pretending to be.

With the Beta 2, however, this changed.  The WPF binding stack had apparently been modified to recognize the ExpandoObject and to treat it on its own terms.  If I have a binding on a TextBox in WPF to an arbitrary property called, for instance, “Name”, all I have to do is add that string to the ExpandoObject’s internal dictionary and the value I added will show up in my TextBox.  Even better, the ExpandoObject automatically supports INotifyPropertyChanged on that new pseudo-property.

           dynamic Employee = new ExpandoObject();
           Employee.Name = "Jim Henson";

This small change makes the ExpandoObject suddenly very useful, especially in situations where we need a glue layer between servers and clients that are indifferent to static typing such as an object layer between a REST service and WPF.

Phil Haack has a playful post about this aspect of programming with the dynamic type on his blog: http://haacked.com/archive/2009/08/26/method-missing-csharp-4.aspx .  He prefaces it with this:

Warning: What I’m about to show you is quite possibly an abuse of the C# language. Then again, maybe it’s not. ;) You’ve been warned.

There’s a lot of truth in this.  On the one hand, dynamic types goes deeply against the grain of anyone who has programmed in C# for the past several years.  I’m not sure how this feels to VB developers who always have had the option to turn Option Strict off in their code.  It gives me the heebie-jeebies, though.

At the same time, it looks extremely fun.  Maybe even a little subversive. I want to start finding applications for this new code feature for working within C# rather than simply using it for interop with supported dynamic languages.

The ExpandoObject does some rather cool things not initially obvious.  For one thing, I can add methods to it as well as properties.  This can be done by passing a delegate to it that references a lambda statement, for instance:

        dynamic obj = new ExpandoObject();

        obj.DoSomething = new Func<string>(() => 
            { Console.WriteLine(DateTime.Now.ToLongTimeString()); return "Hello"; });

        obj.DoSomethingWithParams = new Func<string, bool>((x) => 
            { Console.WriteLine(DateTime.Now.ToLongTimeString());  
                Console.WriteLine(x); 
                return true; 
            });
        Console.WriteLine(obj.DoSomething());
        Console.WriteLine(obj.DoSomethingWithParams("something different"));

Another thing it can do is load properties dynamically (loading a dynamic type dynamically, yeah!) by simply casting it back to the dictionary it really is internally.  Here’s a sample of dynamically loading up an ExpandoObject based on an XML Document:

           XDocument root = XDocument.Load("Employee.xml");
            //convert xml document into an ExpandoObject
           dynamic Employee = new ExpandoObject();

           var EmployeeDictionary = Employee as IDictionary<string, object>;
           foreach (XElement el in root.Elements())
            {
                    EmployeeDictionary.Add(el.Name.LocalName, el.Value);
            }

I now have an object that I can bind to the DataContext of a WPF Window.  I could, of course, have just bound the original XMLDocument to my WPF, but then I wouldn’t have nice extras like INotifyPropertyChanged that I normally expect to have at my disposal in WPF development.

The Dynamic Type is a complicated beast however.  Just reading over Bill Wagner’s post on implementing a Method Bag fills me with anxiety: http://msdn.microsoft.com/en-us/library/ee658247.aspx

That post was nothing, however, compared to this gem I found on Nikhil Kothari’s blog from over a year ago!  http://www.nikhilk.net/CSharp-Dynamic-Programming-REST-Services.aspx

Mr. Kothari builds a class that can point to multiple (and, thanks to the Dynamic Type, interchangeable) REST services and generates properties based on the XML or JSON that comes back.  It does much more than this, also, I think, but Nikhil Kothari is so far beyond me that I have trouble understanding everything that is happening in his code.

The source code, by the way, doesn’t actually compile as it is currently written – but then he did this over a year ago, so…

In any case, walking through and coming to terms with what he has created is certainly one of my goals for November.  It is an implementation that is a game-changer for C# development, and raises Dynamic Types from an oddity to something that will actually solve architectural bottlenecks … at least, I think it does.  As I said, I don’t actually understand it, yet.