How to test if a valid Method exists when params are involved
I have the following method:
public MethodInfo FancyGetMethodInfo
(object obj, string methodName, Type[] methodSignature)
{
return obj.GetType().GetMethod(methodName, methodSignature);
}
and for the sake of an example I have in my object I am passing the two methods
public int Subtract(int a, int b) { return a - b; }
public int Add(params int[] a) { return a.Sum(); }
And when I execute the following lines I get these results:
var SubMethod = FancyGetMethodInfo(obj, "Subtract",
new Type[] { typeof(int), typeof(int) });
//I get a MethodInfo
var AddMethod = FancyGetMethodInfo(obj, "Add",
new Type[] { typeof(int), typeof(int) });
//I get a Null reference
I'm sure this is because of the params in Add. Is there a clean way to get reference to my MethodInfo for my Add method given an arbitrary sized Type[] containing ints and only having access to the provided variables in my FancyGetMethodInfo method?
Edit: More eloquently put by Jon Skeet, I want to perform the same binding as the C# compiler does in my method. it needs to work properly with subclasses, implicit casting, arbitrary length params, etc...
Also as requested, a relevant link he开发者_运维技巧re is: Determining if a parameter uses "params" using reflection in C#? which will get me as far as knowing that the method has a params.
Well, you could:
- Find all the methods with the right name
- For each method:
- Check whether the last parameter in the method is a "params" array (as per this question; thanks yas4891)
- Check whether the parameter types you've been given up to but not including the last parameter match the ones on the method
- Check whether the remaining parameter types all match the array element type of the final parameter
Note that once you'd found a match (and not found a match that didn't require this params expansion) you'd then need to remember that so that you could deal with the arguments appropriately later (assuming you want to actually call the method).
It's a bit of a faff, to be honest... the way I see it you have three options:
- Change the caller to pass in
typeof(int[])
and your existing code will work - Change
FancyGetMethodInfo
to handle parameter arrays as described above - Change
Sum
to accept two integers (or possibly have various overloads)
It's up to you which route you choose...
It's not because of the params (although that may pose an additional issue).
Try instead: var AddMethod = FancyGetMethodInfo(obj, "Add", new Type[] { typeof(int[]) });
A params parameter is nothing more than syntactic sugar for a plain array.
int Add(params int[] a)
is equivalent form a CLR perspective to
int Add(int[] a)
the params modifier is simply C# syntactic sugar.
This means if you want to find you method using reflection you will need the following call:
var AddMethod = FancyGetMethodInfo(obj, "Add",
new Type[] { typeof(int[]) });
if you further wan to test whether the method contains a params parameter you need to test if it has the ParamArrayAttribute applied to the last parameter of the method.
Did you give this one a try:
From the MSDN: Type.GetMethod
public void MethodA(int[] i) { }
// Get MethodA(int[] i)
mInfo = typeof(Program).GetMethod("MethodA",
BindingFlags.Public | BindingFlags.Instance,
null,
new Type[] { typeof(int[]) },
null);
Console.WriteLine("Found method: {0}", mInfo);
How to check for the "params" keyword: this has been answered here
精彩评论