Alternative Syntax for Member Calls on C# Dynamic Types
XML-RPC.NET is essentially concerned with making statically typed calls to XML-RPC endpoints, using interfaces as contract definitions in a similar way to WCF. However the new dynamic type in .NET 4 makes it possible to provide a clean way of making dynamically typed calls, for example like this:
dynamic client = new XmlRpcClient("http://someXmlRpcEndpont");
int returnValue = client.Add(2, 3);
The DynamicObject class in the System.Dynamic namespace makes implementing a dynamic class straightforward:
using System.Dynamic;
class XmlRpcClient : DynamicObject
{
string endpoint;
public XmlRpcClient(string endpoint)
{
this.endpoint = endpoint;
}
public object Invoke(string methodName, object[] args)
{
return 5; // actually make call to XML-RPC endpoint here
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args,
out object result)
{
result = Invoke(binder.Name, args);
return true;
}
}
However, the method name in XML-RPC can be an arbitrary string which is not necessarily representable as a token in C#, for example "samples.Add". JavaScript handles this case by providing an alternative syntax to access a member via a string and then make a call on it, for example:
obj["foo"]() // get member 'foo' and call it
The dynamic type of C# does not support this, at least in the current beta, but it can be implemented:
using System.Dynamic;
class XmlRpcClient : DynamicObject
{
// ...
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes,
out object result)
{
result = (Func)(args => Invoke(indexes[0] as string, args));
return true;
}
public delegate object Func(params object[] args);
}
So making this code possible:
dynamic client = new XmlRpcClient("http://someXmlRpcEndpont");
int returnValue = client["samples.Add"](2, 3);