I want to write this in C#:
SomeUnknownType x;
SuperDuperInvoke(x, "MethodName", param1, param2, param3);
SuperDuperInvoke2(x, "MethodName", "param1String", "param2String", "param3String");
Get some object I know nothing about, a method name, and a list of parameters, and just call the method. SuperDuperInvoke2
assumes the parameters are convertible from string.
I assume something like this is possible using the dynamic framework... I just can't find how...
I know I can do this with Reflection, but it's ugly and annoying...
I'll explain myself a little.
I want to use this for integration testing of some business server. The server has a lot of different components that can handle requests, all loaded into an IoC container. I need to expose some of thees components, mostly for testing, so I want to just receive the name of the component, what method i should call with what parameters and just call it.
You say that you do not like to use reflection, however, since you mention that you only know the methodname as a string, there's only one way: reflection. It's not so hard as you might think. Here's one way:
EDIT: code updated. It now works with overloaded members and any number of parameters. Provided that you know either the type of the parameters, or the parameters are properly initialized to their respective types, this will work.
Note: in your question-text you mention that all params are convertible to string and that you pass the values as strings. But if you have a method like
Calc(int)
andCalc(long)
and you have only a string value to be converted to either of these, you'll need more info about your method because there's no way to know up front which of those methods you should call if all parameters values are stringized.I know you wrote that you don't like Reflection but is this really all that ugly?
If the method could be overloaded you can't go by name only but also need to know how many parameters you are going to invoke it with. Something like this
This will not work if you also need to match your methodParams by type.
When using the
dynamic
keyword you do need to know the method name at compile time, however what that actually compiles down into, are DLR API calls with a string constant for the method name. It's certainly possible to call these yourself, where it become tricky is that the dlr performance is dependent on static caching sites created along side these api calls.The open source framework ImpromptuInterface (found in Nuget) wraps the DLR api with some static invoke methods. It hashes the caching sites, so it's not as fast as the dynamic keyword, but it's at least 2x faster than reflection. The only trick is that if you try to call a void returning method expecting a value it throws an exception when trying to bind. Example implementation:
Since it's open source (apache license) you can always go to the source of InvokeMember etc to help implement your
SuperDuperInvoke
, if you don't want the dependency.SuperDuperInvoke2
is more difficult because the DLR is going to try and match the method based on the argument types, it will take into account implicit conversions, but only statically define ones (TryConvert
onDynamicObject
won't work), so you would then need a proxy that has staticaly defined implicit converts to all your expected types, that can be dangerous watch out for method overloads they will likely be ambiguous toSuperDuperInvoke2
.Without dynamic, you would do this:
Now this is fairly naive in that it isn't looking for a specific method. Best bet is to instead get all methods of that name and filter down to the ones that have the right number parameters then filter those down to the ones that have types that are assignable from the given parameter's types and then select the one with the least upcasts.