Business Integration Solutions Saas

How To: Create a Custom Codeunit with Expression Functions that uses the Namespaced Invokable interface

Concept

The Invokable Namespace interface can expose multiple functions in a codeunit. Which is more flexible than the Invokable0..10

Steps

This scenario is based on methods grouped under one namespace (codeunit). It requires an enum extension based on TICNSInvokable from STAEDEAN-Common, where you will add for each library a new enum value.

  enumextension 50000 "My NS Invokable Enum Ext" extends TICNSInvokable
  {
    value (50000; "My custom function list")
    {
      Implementation = TICINamespacedInvokable = "My custom function list", TICIInvokeRegistrable = "My custom function list";
    }
  }

Your codeunit needs to implement both interfaces: TICINamespacedInvokable and TICIInvokeRegistrable.

The interface TIINamespacedInvokable exposes the Invoke method to you, where you call every function that you need.

It has the following definition:

  !//********************************************************** 
  !//<return>Will hold the method execution result</return>
  !//<method>The method name to invoke</method>
  !//<args>An array holding the required arguments for your method call</args>
  !//********************************************************** 
  procedure Invoke(var return: Variant; method: Text; args: array[20] of Variant);

The interface TICIInvokeRegistrable exposes the RegisterInvokableMethods method to you, where you can register what functions you want to be available

It has the following definition

  !//********************************************************** 
  !//<Registrar>Library that exposes ways of registering methods and arguments</Registrar>
  !//********************************************************** 
  procedure RegisterInvokableMethods(var Registrar: Codeunit TICInvokableRegistrar);

  !//********************************************************** 
  !//The methods that the TICInvokableRegistrar exposes can be seen below
  !//<MethodName>The methods name you want to register</MethodName>
  !//<MethodDescription>The methods description you want to register</MethodDescription>
  !//<ReturnType>The methods return type</ReturnType>
  !//<Namespace>The enum value linked to the codeunit library you are trying to register</Namespace>
  !//********************************************************** 
  procedure RegisterMethod(MethodName: Text[245]; MethodDescription: Text[150]; ReturnType: Enum TICInvokableReturnType; Namespace: Enum TICNSInvokable)

  !//********************************************************** 
  !//<ArgName>The argument name you want to register</ArgName>
  !//<ArgType>The argument type you want to register</ArgType>
  !//********************************************************** 
  procedure AddArguments(ArgName: Text[120]; ArgType: Enum TICInvokableParameterType)

  !//********************************************************** 
  !//<MethodName>The argument name you want to register</MethodName>
  !//<Namespace>The argument type you want to register</Namespace>
  !//The var variables are there to fill by the method metadata based on the method name and namespace
  !//********************************************************** 
  procedure GetMethodMetadata(MethodName: Text[245]; Namespace: Text; var MethodDescription: Text[150]; var ReturnType: Enum TICInvokableReturnType; var ArgumentsList: Codeunit TICInvokableMethodParamColl): Boolean

Example

A full example using the namespaced invokable scenario can be seen below. Note that only one of the 3 functions that are being registered is visible.

codeunit 50000 "My custom function list" implements TICINamespacedInvokable, TICIInvokeRegistrable
{
  procedure XCOPYSTR(String : Text;Position : Integer;Length : Integer) : Text 
  begin
    !//********************************************************** 
    !// category : string 
    !// description: Copies a substring of any length from a specific position in a string (text or code) to a new string. 
    !//********************************************************** 

    exit(copystr(String,Position,Length));
  end;

  procedure Invoke(var return: Variant; method: Text; args: array[20] of Variant)
  begin
    case Method of
      'XCOPYSTR':
        return := XCOPYSTR(args[1], args[2], args[3]);
      'XCOMPANYNAME':
          return := XCOMPANYNAME();
      'Base64Decode':
          return := Base64Decode(args[1]);
      'Base64Encode':
          return := Base64Encode(args[1]);
    end;
  end;

  procedure RegisterInvokableMethods(var Registrar: Codeunit TICInvokableRegistrar)
  var
    ReturnType: Enum TICInvokableReturnType;
    ParameterType: Enum TICInvokableParameterType;
    NSInvokable: Enum TICNSInvokable;
  begin
    Registrar.RegisterMethod('XCOPYSTR', 'Copies a substring of any length from a specific position in a string (text or code) to a new string.', ReturnType::Text, NSInvokable::"BIS Function List 2");
    Registrar.AddArguments('String', ParameterType::Text);
    Registrar.AddArguments('Position', ParameterType::Integer);
    Registrar.AddArguments('Length', ParameterType::Integer);
    Registrar.RegisterMethod('XCOMPANYNAME', 'Gets the current company name.', ReturnType::Text, NSInvokable::"BIS Function List 2");
    Registrar.RegisterMethod('Base64Decode', 'Decodes a base64 encoded value to a string', ReturnType::Text, NSInvokable::"BIS Function List 2");
    Registrar.AddArguments('Base64String', ParameterType::Text);
    Registrar.RegisterMethod('Base64Encode', 'Encodes a string to a base64 value', ReturnType::Text, NSInvokable::"BIS Function List 2");
    Registrar.AddArguments('StringValue', ParameterType::Text);
  end;
}