Servers that support Web Services are built using invokable interfaces. Invokable interfaces are interfaces that are compiled to include runtime type information (RTTI). On the server, this RTTI is used when interpreting incoming method calls from clients so that they can be correctly marshaled. On clients, this RTTI is used to dynamically generate a method table for making calls to the methods of the interface.
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, your Web Service can only use 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 used as part of the Web Service.
When defining a Web service, you can derive an invokable interface from the base invokable interface, IInvokable. IInvokable is defined in the System unit. IInvokable is the same as the base interface (IInterface), except that it is compiled using the {$M+} compiler option. The {$M+} compiler option ensures that the interface and all its descendants 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; end;
__interface INTERFACE_UUID("{C527B88F-3F8E-1134-80e0-01A04F57B270}") IEncodeDecode : public IInvokable { public: virtual double __stdcall EncodeValue(int Value) = 0 ; virtual int __stdcall DecodeValue(double Value) = 0 ; };
Typically, your Web Service client or server creates the code to define invokable interfaces either by importing a WSDL document or using the Web Service wizard. By default, when the WSDL importer or Web Service wizard generates an interface, the definition is added to a unit with the same name as the Web Service. This unit includes both the interface definition and code to register the interface with the invocation registry. The invocation registry is a catalog of all registered invokable interfaces, their implementation classes, and any functions that create instances of the implementation classes. It is accessed using the global InvRegistry function, which is defined in the InvokeRegistry unit.
The definition of the invokable interface is added to the interface section of the unit, and the code to register the interface goes in the initialization section. The registration code looks like the following:
initialization InvRegistry.RegisterInterface(TypeInfo(IEncodeDecode)); end.
static void RegTypes() { InvRegistry()->RegisterInterface(__delphirtti(IEncodeDecode), "", ""); } #pragma startup RegTypes 32
You can use the same unit file to define an invokable interface for both client and server applications. If you are doing this, 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. 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, as long as they both use the same value for the AppNamespacePrefix variable.
The preceding example uses only scalar types (integers and doubles) in the methods of the interface. You can use nonscalar types as well, but they require a bit more work.
Copyright(C) 2008 CodeGear(TM). All Rights Reserved.
|
What do you think about this topic? Send feedback!
|