We have a usecase where we need to invoke an instance of a class and invoke a method at run time using string. I know with reflection i can instantiate a class. But how do we invoke a method of a class at run time? Could you any share some snippets of code for this please?
2 Answers
You can use an interface to ensure that the invoked class has the required method.
Disclaimer: I mostly hacked this together and haven't run it. Hopefully you get the general idea.
global class InterfaceSample {
global interface MyInterface {
void methodToInvoke(string input);
}
global class SampleImplementation implements MyInterface {
global void methodToInvoke(string input) {
System.debug(input);
}
}
}
public with sharing class TestFactoryClass {
public static InterfaceSample.MyInterface getInstance(string className) {
Type t = Type.forName(className);
if(t == null && className != null) {
// Attempt to get the type again with the namespace explicitly set to blank
t = Type.forName('', className);
}
if(t == null) {
System.debug(LoggingLevel.Error, 'Failed to find type for ['+className+']');
return null;
}
// Create an instance to confirm the type
object testInstance = t.newInstance();
if(!(testInstance instanceOf InterfaceSample.MyInterface)) {
return null;
}
InterfaceSample.MyInterface interfaceInstance = (InterfaceSample.MyInterface)testInstance;
return interfaceInstance;
}
}
Then you can just use the factory class to get an instance of the interface and invoke the methods.
InterfaceSample.MyInterface i = TestFactoryClass.getInstance('InterfaceSample.SampleImplementation');
i.methodToInvoke('Hello World');
-
I like the concept here, but dont follow how the method actually gets invoked, where I expected to see this happen I see System.debug(input). Can you tell me how to invoke it?– JoelioSep 5, 2013 at 18:34
-
@Joelio. The
System.debug(input)
line is just a place-holder for your actual implementation. When the factory class returns you the interface instance based on the class name parameter you can be sure themethodToInvoke
method exists. The very final line in the answer shows the method being invoked and passed a sample argument. Sep 5, 2013 at 21:13 -
ok, so you are saying, I have to put if (input == 'Hello World') helloWorld();– JoelioSep 6, 2013 at 13:28
-
@Joelio I'm not sure I follow what you are trying to accomplish. If you have a specific problem or question it might be easier to ask a separate (distinct) question on the site. Sep 6, 2013 at 21:49
-
@DanielBallinger - Good work. This concept is great. For using this concept - Do you see any downside using a virtual class instead of an interface?– BhuvanJun 16, 2016 at 14:39
No Apex does not support reflection. You could vote for the idea...
I have heard it on the grapevine that there are some major changes being done to the apex compiler, which in theory would mean once they have made these changes they can start adding new features like reflection.
Back to your problem, what is the basic problem you are trying to solve? It is possible you may just need to redesign/rethink your solution?
-
We have a multiple step wizard of 60 steps. We are using one controller and 60 vf pages. Each visual force page is mapped to an apex class which the controller would delegate to do the page load, next button and previous button click. The problem is that some pages have like 10 action buttons and more action links and we want a dynamic way to create a run time screen driver which would read an xml file and delegate to an apex class and invoke method instead of changing code. How do we do this without reflection? Mar 15, 2013 at 1:02
-
@buyankumar I didn't say you could do it without reflection, I said you might depending on your problem. Downvoting me because you didn't get the answer you want seems unfair Mar 15, 2013 at 2:58
-
(Ducking) don't throw Buyan under the bus - I downvoted this answer, because a) Apex doesn't entirely support reflection but Type.forName and newInstance are basic reflection support and b) what Buyan is doing can entirely be resolved by a combination of Type.forName, use of Interfaces, and/or command-pattern methods. Daniel Ballinger's answer pretty much nailed it. Sorry for the downvote, but this is an inferior answer to the other one! Mar 15, 2013 at 4:20
-
bunyan sorry I just assumed. @jkraybill thanks for the feedback, you're right my answer isn't as helpful as Daniel's, but it's not wrong, method invocation through apex is not possible, which is what the op is asking about Mar 15, 2013 at 5:28
-
well don't feel bad, I'm possibly the biggest downvoter on this site because I really think it helps make the site better. In this case, people who come to this page should see this answer after Daniel's, which is what I aim to achieve by downvoting. Don't be offended :) Mar 15, 2013 at 5:41