[SalesForce] Call Apex class method on the fly (dynamically)

Is there any way I can call apex method from class if both class name and method are stored in the string.

String strClass = 'BatchUtil';
String strMethod = 'updateAccounts'

now I want to call above method.. is it possible ?

I was doing research and came across following – (not sure how this works and how to call it from salesforce)

ExecuteAnonymousResult[] = binding.executeanonymous(string apexcode);

http://www.salesforce.com/us/developer/docs/apexcode/Content/sforce_api_calls_executeanonymous.htm

Best Answer

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);
   }
}