Call Apex class method on the fly (dynamically)

While you can instantiate a class based on its name using the Type system class, you can't dynamically locate a method and execute it. The best that you can do is to dynamically create an instance of a class that implements an interface and execute one of the methods on the interface.

There's more information on the Type class and an example in the :

Apex Developer's Guide


With the Callable interface that was introduced in Winter '19 you can now build a light weight interface for the methods you want to dynamically call from a class.

The example below is from the docs (tweaked to show dynamic method naming):

Example class you want to dynamically call

public class Extension implements Callable {

   // Actual method
   String concatStrings(String stringValue) {
     return stringValue + stringValue;
   }

   // Actual method
   Decimal multiplyNumbers(Decimal decimalValue) {
     return decimalValue * decimalValue;
   }

   // Dispatch actual methods
   public Object call(String action, Map<String, Object> args) {
     switch on action {
       when 'concatStrings' {
         return this.concatStrings((String)args.get('stringValue'));
       }
       when 'multiplyNumbers' {
         return this.multiplyNumbers((Decimal)args.get('decimalValue'));
       }
       when else {
        throw new ExtensionMalformedCallException('Method not implemented');
       }
     }
   }

   public class ExtensionMalformedCallException extends Exception {}
}

Unit test demonstrating the dynamic calling

@IsTest
private with sharing class ExtensionCaller {

   @IsTest
   private static void givenConfiguredExtensionWhenCalledThenValidResult() {

      // Given
      String className = 'Extension'; // Variable to demonstrate setting class name
      String methodName = 'multiplyNumbers'; // Variable to demonstrate setting method name
      Decimal decimalTestValue = 10;

      // When
      Callable extension = (Callable) Type.forName(className).newInstance();
      Decimal result = (Decimal) extension.call(methodName, new Map<String, Object> { 'decimalValue' => decimalTestValue });

      // Then
      System.assertEquals(100, result);
   }
}

Now this is possible in apex using Tooling API.

> ToolingAPI x = new ToolingAPI(); ToolingAPI.ExecuteAnonymousResult
> toolingResult = x.executeAnonymousUnencoded("Your apex code as a
> string here");

Please refer blog post - http://codefriar.wordpress.com/2014/10/30/eval-in-apex-secure-dynamic-code-evaluation-on-the-salesforce1-platform/

ToolingAPI class is taken from here - https://github.com/afawcett/apex-toolingapi/blob/apex-toolingapi-rest/src/classes/ToolingAPI.cls

Tags:

Apex