To explicitly answer, "Is there a way in VB to dynamically call a method for a function argument without using reflection?":
EDIT: Now I looked at IL disassemblies (via LinqPad) and compared it to CallByName code (via Reflector), and using CallByName uses the usual amount of Reflection , Option Strict Off late binding.
So, the full answer: you can do this with Option Strict Off for all Object references, except when the method you are trying to exist on the Object itself, where you can use CallByName to get the same effect (and, on in fact, this does not need Option Strict Off ).
Dim dynamicValue = CallByName(value, "ToString", CallType.Method, "N3")
NB This is not actually the equivalent of the last call to the binding, which should take into account the possibility that the βmethodβ is actually a (indexed) property, so it actually calls the equivalent:
Dim dynamicValue = CallByName(value, "ToString", CallType.Get, "N3")
for other methods like Double.CompareTo .
More details
Your problem is that Object.ToString() exists, so your code is not trying to dynamically dispatch, but is looking for the default index index for the String.Chars default property String from this call to value.ToString() .
You can confirm that this happens at compile time by trying value.ToString(1,2) , which you would prefer to perform a run-time search for the two ToString parameters, but it actually fails with
Too many arguments in the 'Public ReadOnly Default Chars property (As Integer index) Like Char'
at compile time.
Similarly, you can confirm that all other non- Shared Object methods are called directly using callvirt , relying on Overrides where possible, rather than dynamically sending calls to the Microsoft.VisualBasic.CompilerServices.NewLateBinding namespace if you look at the compiled code in IL .