Reflection: How to Invoke Method with parameters
Change "methodInfo" to "classInstance", just like in the call with the null parameter array.
result = methodInfo.Invoke(classInstance, parametersArray);
Invoke Method with reflection pass through parameters and receive a return value
Have a look at the signature of MethodInfo.Invoke
public object Invoke(
object obj,
object[] parameters
)
You need to pass the parameters of the method in the parameters
object[]
. Note that the method returns an object
, you just need to cast it to the result type.
A call to TestString
should look like this:
var parameters = new object[]{"A string", 10, 'a'};
string result = (string) t.GetMethod("Print").Invoke(t, parameters);
using reflection to invoke methods which takes different parameters
The problem here is in the line
result = this.methodTocall.invoke(null, new Object[]{args});
When you pass arguments to the method, you wrap them in another Object[], which is a) unnecessary and, when args
contains multiple arguments (like the string and the int from your second method call), hides those arguments in the Object
array, making them appear as one parameter. That is why you get the error.
Solve it by using the following changes:
result = this.methodTocall.invoke(null, args);
Then change your main method to this:
String[] a = new String[]{"H","E","L","L","O"};
MethodCalling mc = new MethodCalling("wat.SizeChecker");
mc.setMethod("isTooBig", Comparable[].class);
/* change here: place the single parameter into a parameter array */
Boolean result1 = (Boolean) mc.callMethod(new Object[]{a});
System.out.println("too big="+result1);
mc.setMethod("isCorrectLength",Comparable[].class, int.class);
/* since the callMethod accepts varargs, these are automatically placed in an Object[] */
Boolean result2 = (Boolean) mc.callMethod(a, 5);
System.out.println("length is 5="+result2);
How to invoke with reflection a method that accepts a Func parameter?
There is indeed no conversion from method groups to object
, but there are conversions from method groups to compatible delegate types (method group conversions), and there are also conversions from delegate types to object
. So you can first convert the method group to Func<Expression, Expression, BinaryExpression>
with a cast, then it can be implicitly converted to object
:
someMethodInfo.Invoke(null, new object[] { (Func<Expression, Expression, BinaryExpression>)Expression.Subtract });
How to use reflection to invoke a method with primitive arguments?
When arguments such as 10
or 10.0f
are passed into the method, they are automatically wrapped, because the parameter type is Object...
.
Therefore, you need to check for these wrapper types and unwrap them. Your for loop can look like this:
for(int i = 0; i < args.length; i++) {
if (args[i].getClass() == Integer.class) {
classes[i] = int.class;
} else if (args[i].getClass() == Float.class) {
classes[i] = float.class;
} else if (args[i].getClass() == Double.class) {
classes[i] = double.class;
} else {
classes[i] = args[i].getClass();
}
}
I have only added 3 cases here, you can add the other 5 yourself.
This means that you can't call methods with wrapper type arguments now. If you want to call those as well, you need to
- unwrap all the wrapper types
- try to find a method with those non-wrapper types
- If not found, wrap them up again
- find the a method using the wrapper types.
Edit:
As Holger suggested in the comments, you can also let the JVM find a suitable method for you, by using
new Statement(this, methodName, args).execute();
Docs for the Statement
class.
Invoke method by reflection with dynamic parameters
Actually as @Boris says all I had to do to complete my job was to convert each parameters to the correct type. In this way Java managed to invoke the correct method of the Something
class with the correct parameters types.
My project is a Vert.x
application using Vavr
and jodd
but the last return statement shows how I managed to solve.
public Object invokeMethod(Object service, Method method, RoutingContext routingContext) throws Exception {
MultiMap queryParams = routingContext.queryParams();
Map<String, String> pathParams = routingContext.pathParams();
Buffer body = routingContext.getBody();
// 1. type, 2. name, 3. value
List<Tuple3<Class<?>, String, Object>> list = List.empty();
for (Parameter par : method.getParameters()) {
ParamQuery paramQuery = par.getAnnotation(ParamQuery.class);
if (paramQuery != null) {
list = list.push(new Tuple3<Class<?>, String, Object>(par.getType(), paramQuery.value(),
queryParams.get(paramQuery.value())));
}
}
// TypeConverterManager used to "covnert" each object (String) from the HTTP call to the correct data type
return method.invoke(service, list.reverse()
.map(mapper -> TypeConverterManager.lookup(mapper._1()).convert(mapper._3())).toJavaArray());
}
However, this project can be found on GitHub
How do I invoke a Java method when given the method name as a string?
Coding from the hip, it would be something like:
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
catch (NoSuchMethodException e) { ... }
The parameters identify the very specific method you need (if there are several overloaded available, if the method has no arguments, only give methodName
).
Then you invoke that method by calling
try {
method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) { ... }
catch (IllegalAccessException e) { ... }
catch (InvocationTargetException e) { ... }
Again, leave out the arguments in .invoke
, if you don't have any. But yeah. Read about Java Reflection
How invoke method for a method by default value for parameters by reflection
You can use ParameterInfo.HasDefaultValue
and ParameterInfo.DefaultValue
to detect this. You'd need to check whether the number of arguments you've been given is equal to the number of parameters in the method, and then find the ones with default values and extract those default values.
For example:
var parameters = method.GetParameters();
object[] args = new object[parameters.Length];
for (int i = 0; i < args.Length; i++)
{
if (i < providedArgs.Length)
{
args[i] = providedArgs[i];
}
else if (parameters[i].HasDefaultValue)
{
args[i] = parameters[i].DefaultValue;
}
else
{
throw new ArgumentException("Not enough arguments provided");
}
}
method.Invoke(method.IsStatic ? null : this, args);
Related Topics
Metadataexception: Unable to Load the Specified Metadata Resource
How to Get the Datetime For the Start of the Week
What Does Question Mark and Dot Operator . Mean in C# 6.0
How to Bind a Wpf Datagrid to a Variable Number of Columns
Reading Xml With Xmlreader in C#
How to Exclude Property from Json Serialization
Difference Between Null and System.Dbnull.Value
The Foreach Identifier and Closures
Integer Summing Blues, Short += Short Problem
Dynamic Where Clause (Or) in Linq to Entities
Using Parameters Inserting Data into Access Database
How to Get Httpcontext.Current in ASP.NET Core
How to Monitor SQL Server Table Changes by Using C#
Best Way to Compare Two Complex Objects
Show Console in Windows Application
How to Enable C# 6.0 Feature in Visual Studio 2013
How to Modify a CSS Style in the Code Behind File for Divs in ASP.NET