Define an interface
The current implementation of service has the following expectations:
- Any interface inheriting from IInvokable, with a GUID, can be
used - we expect the RTTI to be available, so IInvokable is a good
parent type;
- You can inherit an interface from an existing one: in this case, the
inherited methods will be part of the child interface, and will be expected to
be implemented (just as with standard Delphi code);
- Only plain ASCII names are allowed for the type definition (as it is
conventional to use English spelling for service and operation naming);
- Calling convention shall be register (the Delphi's default) -
nor stdcall nor cdecl is available yet, but this
won't be a restriction since the interface definition is dedicated
to Delphi code scope;
- Methods can have a result, and accept per-value or per-reference
parameters.
In fact, parameters expectations are the following:
- Simple types (strings, numbers, dates, sets and enumerations) and high-level
types (objects, collections, records and dynamic arrays) are handled - see
below for the details;
- They can be defined as const, var or
out - in fact, const and var parameters
values will be sent from the client to the server as JSON, and var
and out parameters values will be returned as JSON from the
server;
- procedure or function kind of method definition are
allowed;
- Only exception is that you can't have a function returning a
class instance (how will know when to release the instance in this
case?), but such instances can be passed as const,
var or out parameters (and published
properties will be serialized within the JSON message).
Available types for methods
Handled types of parameters are:
| Delphi type | Remarks |
boolean |
Transmitted as JSON true/false |
integer cardinal Int64 double currency TDateTime |
Transmitted as JSON numbers |
| enumerations | Transmitted as JSON number |
| set | Transmitted as JSON number - one bit per element (up to 32 elements) |
RawUTF8 WideString |
Transmitted as JSON text (UTF-8 encoded) |
string |
Transmitted as UTF-8 JSON text, but prior to Delphi 2009, the framework
will ensure that both client and server sides use the same ANSI code page - so
you should better use RawUTF8 |
TPersistent |
Published properties will be transmitted as JSON object |
TSQLRecord |
All fields (including ID) will be transmitted as JSON object |
| dynamic arrays | Transmitted as JSON arrays |
record |
Transmitted as binary with Base-64 encoding, needed to have RTTI (so a
string or dynamic array field within), just like with regular Delphi
interface expectations |
You can therefore define complex interface types, as such:
type
ICalculator = interface(IInvokable)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
/// add two signed 32 bit integers
function Add(n1,n2: integer): integer;
/// multiply two signed 64 bit integers
function Multiply(n1,n2: Int64): Int64;
/// substract two floating-point values
function Subtract(n1,n2: double): double;
/// convert a currency value into text
procedure ToText(Value: Currency; var Result: RawUTF8);
/// convert a floating-point value into text
function ToTextFunc(Value: double): string;
/// do some work with strings, sets and enumerates parameters,
// testing also var (in/out) parameters and set as a function result
function SpecialCall(Txt: RawUTF8; var Int: integer; var Card: cardinal; field: TSynTableFieldTypes;
fields: TSynTableFieldTypes; var options: TSynTableFieldOptions): TSynTableFieldTypes;
/// test integer, strings and wide strings dynamic arrays, together with records
function ComplexCall(const Ints: TIntegerDynArray; Strs1: TRawUTF8DynArray;
var Str2: TWideStringDynArray; const Rec1: TVirtualTableModuleProperties;
var Rec2: TSQLRestCacheEntryValue): TSQLRestCacheEntryValue;
end;
Note how SpecialCall and ComplexCall methods have
quite complex parameters definitions, including dynamic arrays, sets and
records.
The framework will handle const and var parameters
as expected, i.e. as input/output parameters, also on the client side. And
simple types of dynamic arrays (like TIntegerDynArray,
TRawUTF8DynArray, or TWideStringDynArray) will be
serialized as plain JSON arrays - the framework is able to handle any dynamic
array definition, but will serialize those simple types in a more AJAX
compatible way.
Continue reading...
This article is part of a list of other blog articles, extracted from the official Synopse mORMot framework documentation:- Interface based services;
- Defining a data contract;
- Service side implementation;
- Using services on the Client or Server sides;
- Interface based services implementation details.
- WCF, mORMot and Event Sourcing.
Feedback and questions are welcome on our forum, just as usual.
