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.