#TIL: Interrogating Generic Parameters From a Dynamic Object

If, for some reason, you find yourself trying to determine the generic type specified on a dynamic method, have I got a code snippet for you!

In our project’s codebase we have a class that we use as a proxy to all the different WCF endpoints on a different service which we interact with on a regular basis. Originally if we wanted to talk to the service we’d have to download a versioned DLL that corresponded to the server version we wanted to chat with. Normally not a big deal, but due to the nature of our setup we have several versions in production at any given time, and our one web application needs to talk to all of them, so using a versioned DLL wouldn’t work.

Instead we rolled a dynamic proxy class that created the appropriate SOAP envelope when talking to whatever version we needed, and automatically deserializes the response. We can control the returned type by specifying a generic argument on the method call. A typical method execution would look like this:

1
2
3
//names changed to protect the innocent
var service = new ProxyService<IInvoiceService>("4.1.0");
service.GetInvoiceByID<Invoice>(5);

Pretty nifty, eh? The tricky part is how we find out which object to return, in this case an “Invoice”. Normally you’d be able to get the MethodInfo of the current executing method and get the TypeArguments from there, but we’re using a dynamic object – our executing method is always TryInvokeMember. Luckily when we execute TryInvokeMember we’re passed some additional information, namely the InvokeMemberBinder.

InvokeMemberBinder is an object that contains information about the dynamic call that is trying to be executed. For example, binder.Name gives you the name of the method that someone tried to execute. There’s also a few hidden gems in there – using this trick we’re able to get a list of type arguments used in the dynamic method call:

1
2
3
4
5
//this gets an interface that's only specified on the runtime implementation
var csharpBinder = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder"); 

//this executes the TypeArguments property getter against our binder object
var typeArgs = csharpBinder.GetProperty("TypeArguments").GetValue(binder, null) as IList<Type>; 

So using the awesome power of reflection, we can interrogate the runtime instance of InvokeMethodBinder for the type arguments that were passed to the dynamic method! You just leveled up your C#!

(We borrowed this trick from a stackoverflow post)

Comments