Defining invokable interfaces

To create an invokable interface, you need only compile an interface with the {$M+} compiler option. The descendant of any invokable interface is also invokable. However, if an invokable interface descends from another interface that is not invokable, clients of your Web Service server can only call the methods defined in the invokable interface and its descendants. Methods inherited from the non-invokable ancestors are not compiled with type information and so can't be called by clients.

Delphi defines a base invokable interface, ¬°Invokable, that can be used as the basis of any interface exposed to clients by a Web Service server. ¬°Invokable is the same as the base interface (IInterface), except that it is compiled using the {$M+} compiler option so that it and all its descendants are compiled to include RTTI.

For example, the following code defines an invokable interface that contains two methods for encoding and decoding numeric values:

IEncodeDecode = interface (IInvokable)

['{C527B88F-3F8E-1134-80e0-01A04F57B270}'] function EncodeValue(Value: Integer): Double; stdcall; function DecodeValue(Value: Double): Integer; stdcall;


Before a Web Service application can use this invokable interface, it must be registered with the invocation registry. On the server, the invocation registry entry allows the invoker component (THTTPSOAPPascalInvoker) to identify an implementation class to use for executing interface calls. On client applications, an invocation registry entry allows components to look up information that identifies the invokable interface and supplies information on how to call it.

In the initialization section of the unit that defines the interface, add code to register the interface with the invocation registry. To access the invocation registry, add the InvokeRegistry unit to the uses clause of your unit. The InvokeRegistry unit declares a global variable, InvRegistry, which maintains in memory a catalog of all registered invokable interfaces, their implementation classes, and the factories that create instances of the implementation classes.

When you are finished, the unit that defines the interface should look something like the following:

unit EncodeDecode;

interface type

IEncodeDecode = interface(IInvokable)

['{C527B88F-3F8E-1134-80e0-01A04F57B270}'] function EncodeValue(Value: Integer): Double; stdcall; function DecodeValue(Value: Double): Integer; stdcall;


implementation uses InvokeRegistry;


InvRegistry.RegisterInterface(TypeInfo(IEncodeDecode)); end.

Because the interfaces of Web Services must have a namespace to identify them among all the interfaces in all possible Web Services, when you register an interface the invocation registry automatically generates a namespace for the interface. The default namespace is built from a string that uniquely identifies the application (the AppNamespacePrefix variable), the interface name, and the name of the unit in which it is defined.

Tip It is a good idea to keep the unit that defines your invokable interfaces separate from the unit in which you write the classes that implement them. This unit can then be included in both the client and the server application. Because the generated namespace includes the name of the unit in which the interface is defined, sharing the same unit in both client and server applications enables them to automatically use the same namespace.

Was this article helpful?

+1 0

Post a comment