Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a function using reflection that has a "params" parameter (MethodBase)

I have MethodBases for two functions:

public static int Add(params int[] parameters) { /* ... */ }
public static int Add(int a, int b) { /* ... */ }

I have a function that calls the MethodBases via a class I made:

MethodBase Method;
object Target;
public object call(params object[] input)
{
    return Method.Invoke(Target, input);
}

Now if I AddTwoMethod.call(5, 4); it works fine.

If I however use AddMethod.call(5, 4); it returns:

Unhandled Exception: System.Reflection.TargetParameterCountException: parameters do not match signature

Is there any way to make it so that both calls work fine without need for manually putting the arguments in an array for the params int[]?

like image 716
Blam Avatar asked Jun 26 '11 14:06

Blam


1 Answers

You could modify your call method to detect the params parameter and convert the rest of the input to a new array. That way your method could act pretty much the same as the logic C# applies to the method calling.

Something i quicly constructed for you (be aware that i tested this method in a pretty limited way, so there might be errors still):

public object call(params object[] input)
{
    ParameterInfo[] parameters = Method.GetParameters();
    bool hasParams = false;
    if (parameters.Length > 0)
        hasParams = parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0;

    if (hasParams)
    {
        int lastParamPosition = parameters.Length - 1;

        object[] realParams = new object[parameters.Length];
        for (int i = 0; i < lastParamPosition; i++)
            realParams[i] = input[i];

        Type paramsType = parameters[lastParamPosition].ParameterType.GetElementType();
        Array extra = Array.CreateInstance(paramsType, input.Length - lastParamPosition);
        for (int i = 0; i < extra.Length; i++)
            extra.SetValue(input[i + lastParamPosition], i);

        realParams[lastParamPosition] = extra;

        input = realParams;
    }

    return Method.Invoke(Target, input);
}

Be aware that i tested this method in a pretty limited way, so there might be errors still.

like image 52
Jan-Peter Vos Avatar answered Sep 24 '22 08:09

Jan-Peter Vos