Problems with CreateMethodReturn when method has output parameters

May 23, 2012 at 9:12 PM
Edited May 23, 2012 at 9:13 PM

I have a validation ICallHandler that has the following code for Invoke:

 

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
    // validate the arguments
   
if (!this.ValidateArguments(input.MethodBase.Name, input.Arguments))
    {
        return
input.CreateMethodReturn(-1, input.Arguments);
    }

    // Perform the operation
    

return getNext().Invoke(input, getNext);
}

 The ValidateArguments method returns true if the arguments are valid, else false. When this runs with a method that does not have any out parameters it works fine. When it runs with a method that does have out parameters it gets an out of range exception in ParameterCollection.cs in this method:

 /// <summary>
/// Gets the value of a parameter based on index.
/// </summary>
/// <param name="index">Index of parameter to get the value for.</param>
/// <value>Value of the requested parameter.</value>
public object this[int index]
{
   
get { return arguments[argumentInfo[index].Index]; }
   
set { arguments[argumentInfo[index].Index] = value; }
}

The error occurs when the arguments are invalid and I call CreateMethodReturn to change the return value to -1. If the arguments are valid, then everything works fine. Does anyone have any ideas for how to make this work?

 

 

 

 

 

 

May 24, 2012 at 8:10 AM

CreateMethodReturn expects an object returnValue and an optional object array as params.  However input.Arguments is an IParameterCollection and not an object array so instead of passing in the full list of arguments, an object array is passed in containing one item (the IParameterCollection).  This innocuous error results in a confusing index out of range exception.

In the CallHandler if the arguments do not pass validation -1 is returned.  It's not clear to me what the output variable parameter should be set to.  Based on the code snippet it doesn't look like it's being explicitly set to anything (or is ValidateArguments manipulating argument values?).  If in the case of a validation failure it is acceptable to return the default value for the output parameter then you do not need to specify any arguments:

return input.CreateMethodReturn(-1); 

Unity will take care of adding in the appropriate arguments for you.  Or if you want to manually return the outputs then convert to an object array:

return input.CreateMethodReturn(-1, input.Arguments.Cast<object>().ToArray());

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

May 24, 2012 at 2:22 PM

using input.CreateMethodReturn(-1) does not work if you have both input and output parameters. Take this method for example:

public int Addition(int x, int y, out int res)

When you call CreateMethodReturn(-1), the argumentInfo array ends up with one item and the arguments array has one item (since it only copies the output parameter values). However, the one argumentInfo item references index 2 in the arguments array which causes the problem. All of the argument values need to be copied to the arguments array to make it work, or all output parameters need to be specified before any input parameters, which would be a workaround.

May 24, 2012 at 6:02 PM

That is the exact scenario, I was testing (actually public int Sum(int x, int y, out int z) ).  And CreateMethodReturn(-1) works fine in my testing.  

Yes, all of the arguments need to be in the list as per the CreateMethodReturn documentation:

outputs
All arguments passed or returned as out/byref to the method. Note that this is the entire argument list, including in parameters.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com