在运行注册DataSnap服务器类时发布provider

来源:互联网 发布:淘宝宝贝怎么被删除了 编辑:程序博客网 时间:2024/06/05 21:56

A while ago I published a blog post about How to register DataSnap Server Class in runtime with Delphi, after that I got some feedback mentioning the source code I provided just publishes the Server Methods, and not the Providers as part of the Server Module, in other words the client application couldn’t see the Providers available on the DataSnap Server.

The solution for this issue is very simple, we just need to register the TDSProviderDataModuleAdapter class, which is used internally to allow a TProviderDataModule to be exposed to DataSnap clients. TDSProviderDataModuleAdapter acts as a proxy between a server-side TProviderDataModule and client-sides TDSProviderConnection.

We could just update the GetDSClass method implementation as below, it works, but it would not be the best implementation, just because the following code will always publish the IAppServer interface methods to the client side, in case your ServerModule doesn’t have any Provider, why you will publish the IAppServer? Doesn’t make sense, right?

Making the publication parameterizable will bring more flexibility and control to the application and the developer, it will be your decision to publish the Providers or not. A new parameter in the TSimpleServerClass constructor is everything we need.

function TSimpleServerClass.GetDSClass: TDSClass;

1begin
2  Result := TDSClass.Create(FPersistentClass, False);
3  Result := TDSClass.Create(TDSProviderDataModuleAdapter, Result)
4end;

The following code represents the new implementation for the TSimpleServerClass. The change adds a new parameter (ExposeProvider) to the constructor, which will allow the developer to publish the providers (or not).

01type
02 
03unit SimpleServerClass;
04 
05interface
06 
07uses DSServer, Classes, DSCommonServer, DSReflect;
08 
09type
10 
11  TSimpleServerClass = class(TDSServerClass)
12  private
13    FPersistentClass: TPersistentClass;
14    FExposeProvider : Boolean;
15  protected
16    function GetDSClass: TDSClass; override;
17  public
18    constructor Create(AOwner: TComponent; AServer: TDSCustomServer;
19      AClass: TPersistentClass; ExposeProvider: Boolean; ALifeCycle: String);
20      reintroduce; overload;
21  end;
22 
23implementation
24 
25constructor TSimpleServerClass.Create(AOwner: TComponent;
26  AServer: TDSCustomServer; AClass: TPersistentClass; ExposeProvider: Boolean;
27  ALifeCycle: String);
28begin
29  inherited Create(AOwner);
30  FPersistentClass := AClass;
31  FExposeProvider  := ExposeProvider;
32  Self.Server := AServer;
33  Self.LifeCycle := ALifeCycle;
34 
35end;
36 
37function TSimpleServerClass.GetDSClass: TDSClass;
38var
39  isAdapted : Boolean;
40begin
41  isAdapted := FPersistentClass.InheritsFrom(TProviderDataModule);
42  Result := TDSClass.Create(FPersistentClass, isAdapted);
43  if FExposeProvider and isAdapted then
44     Result := TDSClass.Create(TDSProviderDataModuleAdapter, Result)
45end;
46 
47end.

The following code registers 3 classes, where only one exposes the Providers:

view source
print?
1procedure RegisterServerClasses(AOwner: TComponent; AServer: TDSServer);
2begin
3  Assert(AServer.Started = false'Can''t add class to non active Server');
4 
5  TSimpleServerClass.Create(AOwner, AServer, TGlobal, False, TDSLifeCycle.Server);
6  TSimpleServerClass.Create(AOwner, AServer, TCustomer, True, TDSLifeCycle.Session);
7  TSimpleServerClass.Create(AOwner, AServer, TObjectPool, False, TDSLifeCycle.Invocation);
8end;