How to use reflection to call method by name
Something along the lines of:
MethodInfo method = service.GetType().GetMethod(serviceAction);
object result = method.Invoke(service, new object[] { request });
return (R) result;
You may well want to add checks at each level though, to make sure the method in question is actually valid, that it has the right parameter types, and that it's got the right return type. This should be enough to get you started though.
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
Call methods using names in C#
Sure, you can do it like this:
public class Test
{
public void Hello(string s) { Console.WriteLine("hello " + s); }
}
...
{
Test t = new Test();
typeof(Test).GetMethod("Hello").Invoke(t, new[] { "world" });
// alternative if you don't know the type of the object:
t.GetType().GetMethod("Hello").Invoke(t, new[] { "world" });
}
The second parameter of Invoke() is an array of Object containing all the parameters to pass to your method.
Assuming the methods all belong to the same class, you could have a method of that class something like:
public void InvokeMethod(string methodName, List<object> args)
{
GetType().GetMethod(methodName).Invoke(this, args.ToArray());
}
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);
How to call method by name using Kotlin Reflection?
try this:
obj::class.members.firstOrNull { it.name == "methodName" }?.call(argument1, argument2, ...)
How to use reflection to call a API by string name?
You can use a combination of:
Type.GetType(string)
Type.GetMethod(string)
IIocResolver.ResolveAsDisposable(Type)
— by ABPMethodInfo.Invoke(Object, Object[])
// var appServiceName = "MyAppService";
// var methodName = "MyMethod";
// var input = new object[] { new MyInput() };
var appServiceType = Type.GetType(appServiceName);
var method = appServiceType.GetMethod(methodName);
using (var appService = IocResolver.ResolveAsDisposable(appServiceType))
{
var output = await (Task)method.Invoke(appService.Object, input);
}
(Reflection) Calling A Method With Parameters By Function Name In Swift
First of all, as you noted Swift doesn't have full reflection capabilities and rely on the coexisting ObjC to provide these features.
So even if you can write pure Swift code, you will need Solution
to be a subclass of NSObject
(or implement NSObjectProtocol
).
Playground sample:
class Solution: NSObject {
@objc func functionName(greeting: String, name: String) {
print(greeting, name)
}
}
let solutionInstance = Solution() as NSObject
let selector = #selector(Solution.functionName)
if solutionInstance.responds(to: selector) {
solutionInstance.perform(selector, with: "Hello", with: "solution")
}
There are other points of concern here:
- Swift's
perform
is limited to 2 parameters - you need to have the exact signature of the method (#selector here)
If you can stick an array in the first parameters, and alway have the same signature then you're done.
But if you really need to go further you have no choice than to go with ObjC, which doesn't work in Playground.
You could create a Driver.m file of the like:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
id call (NSObject *callOn, NSString *callMethod, NSArray <NSObject *>*callParameters)
{
void *result = NULL;
unsigned int index, count;
Method *methods = class_copyMethodList(callOn.class, &count);
for (index = 0; index < count; ++index)
{
Method method = methods[index];
struct objc_method_description *description = method_getDescription(method);
NSString *name = [NSString stringWithUTF8String:sel_getName(description->name)];
if ([name isEqualToString:callMethod])
{
NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:description->types];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
NSObject *parameters[callParameters.count];
for (int p = 0; p < callParameters.count; ++p) {
parameters[p] = [callParameters objectAtIndex:p];
[invocation setArgument:¶meters[p] atIndex:p + 2]; // 0 is self 1 is SEL
}
[invocation setTarget:callOn];
[invocation setSelector:description->name];
[invocation invoke];
[invocation getReturnValue:&result];
break;
}
}
free(methods);
return (__bridge id)result;
}
Add it to a bridging-header (for Swift to know about what is in ObjC):
// YourProjectName-Bridging-Header.h
id call (NSObject *callOn, NSString *callMethod, NSArray *callParameters);
And call it with a Solution.swift like this:
import Foundation
class Solution: NSObject {
override init() {
super.init()
// this should go in Driver.swift
let result = call(self, "functionNameWithGreeting:name:", ["Hello", "solution"])
print(result as Any)
}
@objc
func functionName(greeting: String, name: String) -> String {
print(greeting, name)
return "return"
}
}
output:
Hello solution
Optional(return)
Edit: compilation
To compile both ObjC and Swift on the command line you can first compile ObjC to an object file:
$ cc -O -c YouObjCFile.m
Then compile your Swift project with the bridging header and the object file:
$ swiftc -import-objc-header ../Your-Bridging-Header.h YouObjCFile.o AllYourSwiftFiles.swift -o program
working sample
Using Reflection to call a method of a property
That was quick... I changed the Invoke line to...
m.Invoke(p.GetValue(newControl, null), new object[] { newValue });
...and it worked :P
Related Topics
Declaration Suffix for Decimal Type
Compare Version Numbers Without Using Split Function
Routing: the Current Request for Action [...] Is Ambiguous Between the Following Action Methods
Recursive Hierarchy - Recursive Query Using Linq
Tabcontrol with Close and Add Button
Outofmemoryexception While Populating Memorystream: 256Mb Allocation on 16Gb System
Linq to SQL Multiple Tables Left Outer Join
Handling Exceptions, Is This a Good Way
How to Sum Up an Array of Integers in C#
How to Read Data from a Zip File Without Having to Unzip the Entire File
Populate Data Table from Data Reader
Create Bitmap from a Byte Array of Pixel Data
Matching Strings with Wildcard
Why Is Array.Length an Int, and Not an Uint
How to Set Timer Resolution from C# to 1 Ms
How to Deserialize JSON with Duplicate Property Names in the Same Object
How to Capture a 0..1 to 0..1 Relationship in Entity Framework