Calling methods by its name (as string)

Hi all,

I have a list of names for methods as:

allScripts = Array(“MethodOne”, “MethodOne Two”, “MethodThree”)

Each of the list item correspond to exactly to a method’s name.
I would like to do something like:

For Each aMethod As string in allScripts then
run aMethod // invoke aMethod // call aMethod …
end

How can achieve this?
I checked the forum and its seems that “Introspection” might do the job.
Is there any simpler way to do it?
If not, can someone share code to convert “names” into methods using “Introspection” ?

(I could do it with Select Case, but the list of methods is long …)

Thanks in advance
Luciano

You can do this with a dictionary and delegates.

Your dictionary key would be the method name, the value would be the delegate (AddressOf Methodname).

A delegate is a pre-defined method signature (parameters and/or return value).
You can then invoke this method delegate

it’s an advanced way of doing this but most likely the only one.

https://documentation.xojo.com/api/language/delegate.html#delegate

read more here:

Further, depending on your use case, you can skip the array of strings entirely and just make an array of delegates.

4 Likes

I have bee trying trying to guess /reading how to do it.
So I add a “delegates” in the main window with:
Delegate name: MethodCaller
Parameters: p As Dictionary
Return type: left it empty

The in a push button action I had this code:

Var myDict As New Dictionary
myDict.Value(“A”) = AddressOf scriptOne
myDict.Value(“B”) = AddressOf scriptTwo
myDict.Value(“C”) = AddressOf scriptThree

Var callMethod As MethodCaller
callMethod.Invoke(myDict.Key(1))

The scriptOne /two/ three are very simple methods (located in the same window) that show a MessageBox. Just as test…

But it does not work …

Var m As methodcaller = mydict.lookup("a", nil)
if Not (m Is Nil) then
M.invoke
End if

You are overthinking or misunderstanding the solution to “call a method by string” perhaps.

Did you mean to parse an argument into the delegate or?

By the dict one simply predefines strings that “own” a delegate this way. That means you can lookup the address and invoke (call) it.

Thanks for your help Derk!
I do not need to pass an argument into the delegate. I just want to call a method by using its name as a string. The name is part of an array of entries which matched perfectly the name of several methods.

I would like to iterate every item of the array and calling the corresponding methods.

The example you just provided me trigger an error when I try to run;
"Not enough arguments: missing Dictionary value for parameter “p”
m.invoke"

Thanks again !

Really simple, lo-tech method is to create a method to do this and call the real method in a Case statement that checks the string you pass it. I do this often. :smile:

It is true, Select Case does the trick! And I mentioned this in my first post.

I wanted to use this as an excuse to learn something new, and I though that in this way it would have required less effort to update the code.

Sorry, I read your post too quickly.

I will test this when I have access to my computer (perhaps only tomorrow). I know I have used AddressOf successfully in various situations (ex: timers, custom listbox type containers).

Just to test appropriately:
• what Xojo version (2022r1.1?)

Thanks.

Select Case is the simplest and most easy to maintain. Don’t overthink this one, Xojo doesn’t support it. There are some convoluted ways to do it, but it’s just not worth it. Choose something else as a learning opportunity.

4 Likes

This is the best advice. I’ve used the introspection route in the past, and it worked 99.99% of the time. But every once in a while a user would hit an exception, relaunch, and it would then be like the intended code never existed. The code signature was still intact, but it would report that there were no matching method signatures even though I know there was. The only solution was for the user to reinstall.

I switched to a Select statement and the problem never came back. It’s cumbersome, but the best answer.

2 Likes

Create a method that takes the method name (as string) as a parameter. The method should contain nothing but the select case that calls the appropriate method based on the name. Use that wherever you need to call a method by name. That way the code to translate the name to a method call exists in only one place. Oh, and throw an exception of the name doesn’t translate to a method, so you’ll know to fix your code if you forget one.

OK. I will go for ‘Select Case’.
Thanks to all.

1 Like