Creating a “Supernatural” Self-Adapting REST Proxy in C#

.NET 4.0’s DynamicObject provides a quick and easy way to hook into and control how a call for a method is dispatched at runtime.  This so called “late dispatch” capability is exactly what we need to easily create dynamic facades over out-of-process APIs, such as those of remote REST services.

In this post, I’ll show you how to take advantage of dynamic dispatch, in order to create an adaptive web agent that gets driven through a normal C# class API.  What I mean by normal, is that familiar dot syntax for calling methods from our objects.  However, in this case the methods we will be calling are not actually there; they are “ghost methods”.   They do not exist on the object whose receiving the call.  This might sound a bit strange to the uninitiated, but fear not, you’re about to get your secret decoder rings.  C#’s DynamicObject gives us the opportunity to delegate to remote service APIs transparently, without the knowledge or concern of the caller. 

To demonstrate this in action, I created a small class called Flickr.  It inherits from DynamicObject and serves as our call dispatcher to Flickr’s REST API, which is available here: http://api.flickr.com/services/rest/.  Here is the API documentation: http://www.flickr.com/services/api/.  You can get API keys here: http://www.flickr.com/services/apps/create/apply.

Each call you see in this TestMethod is actually to a method that does not exist in the definition of the Flickr class.

[TestMethod]
public void Testing_Flickr()
{
    dynamic flickr = new Flickr();
 
    var xml1 = flickr.people_findByUsername(username: "duncandavidson");
 
    var xml2 = flickr.collections_getTree(user_id: "59532755@N00");
 
    var xml3 = flickr.urls_getUserPhotos(user_id: 59532755@N00);
}

Each of these calls succeeds, and returns a response from Flickr’s service.  Note a few things about this code.  Flickr’s API has methods that look like this flickr.people.findByUsername and flickr.urls.getUserPhotos.  Notice the similarity above.  What I’ve done is replaced the dots with underscores, in order to make the functions legal C# method names.  As you’ll see below, we reformat the method name before attempting to call it on the remote Flickr service.  Additionally, note that we are using named parameters above in order to pass in both parameter name and parameter value to our ghost methods.  This allows us to pass any number of key-value paired parameters to any method name we want.  Here is the implementation of the Flickr class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using System.Net;
 
public class Flickr : DynamicObject
{
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        dynamic request;
 
        request = new Func<object>(() =>
        {
            //format methodname
            var remoteMethodName = binder.Name.Replace('_', '.');
 
            //format parameters
            var queryStringBuilder = new StringBuilder();
            for (var i = 0; i < binder.CallInfo.ArgumentNames.Count; i++)
            {
                queryStringBuilder.Append(binder.CallInfo.ArgumentNames[i] + "=" + args[i] + "&");
            }
 
            //build rest message
            var baseUrl = http://api.flickr.com/services/rest/;
            var message = string.Format(baseUrl + "?method=flickr.{0}&{1}api_key=YOUR_KEY_HERE",
                                        remoteMethodName,
                                        queryStringBuilder.ToString());
 

            //send
            var strResponse = new WebClient().DownloadString(message);
 
            //respond
            return strResponse;
        });
 
        result = (request as Delegate).DynamicInvoke(); //no need to pass args. they were set via closures above
        return true;
    }
}
 

As you can see, its DynamicObject’s TryInvokeMember method that is our seam for redelegating the call out to the web.   You may be asking yourself, why in the world would I want to do this.  The biggest advantage is that your local proxy API will always stay in sync with the Flickr service.  Even if they, extend the remote API I can call those methods without having to write a single line of additional plumbing code.  The reason is the responder to the call is not the actual Flickr class, but rather Flickr itself out on the web.  This seems simple and natural.  As it turns out, this type of runtime metaprogramming is becoming the preferred approach to interacting with cloud services via dynamic languages such as Python, Ruby, and JavaScript.  It enables applications to adapt to changes in one another’s interfaces automatically.   Now that C# has been endowed with dynamic, we can capitalize on the feature to build client-server apps that are less brittle and require little to no maintenance around the edges.  Perhaps best of all, the client api automatically already supports new behaviors immediately when they show up on the server. Thats instant gratification for the extraordinarily low price of free.

Giving Your Data Some Higher Order Muscle With C#

Today a colleague and I were going through some code.  I have recently been trying to impart to him the power and beauty in the functional programing paradigm in C#.  Today, the opportunity to demonstrate it presented itself as I was showing him how to use extension methods to extend Entities and ValueObjects with a suite-to-purpose functional API.  As we began the code, I realized that what I really wanted to show him was the concept with no additional fluff.  First, the extension method part.

Here’s what I came up with:

public static class IntExtensions
{
    public static void Times(this int count, Action<int> action)
    {
        for (var i = 0; i < count; i++)
        {
            action(i);
        }
    }
}

This small extension to the builtin int type, gives us a convenient and expressive functional API, driven directly from Int32 typed variables themselves.  Now, we can use it as follows.

[TestMethod]
public void SampleRepository_Can_Create_New()
{
     10.Times(i =>
     {
          var sample = TestObjects.BuildSample();
          SampleRepository.Save(sample);
     });

     var samples = SampleRepository.GetAll();
     
     samples.Count().Times(i => Debug.WriteLine("your index is " + i));

     Assert.IsTrue(samples.Count() == 10, "Should have 10 samples");
}

Rubyists recognize this API as its built into the language. Its simple stepwise iteration driven directly off numeric types. In C# we can use extension methods to shim this behavior into our scalers. APIs that read like 5.Times(doSomething); read like English.  This makes our code  more comprehensible by everyone, and that ladies and gentlemen is worth its weight in Gold Pressed Latinum