在过去客户端要调用远程服务器的方法需要通过在TLB里添加接口并且在服务器对象中实现
在DataSnap 2009中调用远程服务器的方法是基于delphi的RTTI机制的
想要一个类允许被远程调用需要做以下两点
1.把该类和DSServerClass连接在一起
var PersistentClass: TPersistentClass);
begin
PersistentClass : = TSM;
end ;
DSServerClass的OnGetClass就是用于完成此任务的
注意:DSServerClass必须设置要导出的类 否则会出现SOnGetClassNotSet的异常信息
2.该类必须使用$MethodInfo编译指令生成详细的RTTI信息
TDSServerModule = class(TProviderDataModule)
end ;
{ $MethodInfo OFF }
我们查看TDSServerModule的定义发现已经完成了该步骤
所以我们使用向导添加的ServerModule 不需要再手动添加$MethodInfo开关
同样我们也可以不用继承自TDSServerModule来实现我们的ServerClass
只要从TPersistent继承一个类 并且用{$MethodInfo ON}和{$MethodInfo OFF}包围就可以输出成员函数到客户端
注意:要输出的成员函数必须声明为public
客户端调用可以使用两种方法
1.使用SqlServerMethod组件
通过设置其ServerMethodName属性来进行远程调用 使用Params属性来传递参数和结果值
2.使用本地代理类
选中SQLConnection组件,在右键菜单中单击Generate Datasnap client classe 生成代理类单元。
下面我们通过一个简单的DEMO来展示DataSnap 2009的远程方法调用
我们在服务端定义了4个输出的成员函数
public
function Hello(Message: String): String;
function VariantMethod(Value: OleVariant): OleVariant;
function StreamMethod: TStream;
function VarOutMethod(out OutParam: OleVariant; var VarParam: OleVariant): string;
end ;
由于在DataSnap内部是使用TDBXValue来管理参数列表的
所以使用string等delphi语言自带的类型将会进行相应的映射
使用TDBXValue也是效率最高的
以下是可以作为参数使用的TDBXValue列表
TDBXWideStringValue
TDBXAnsiStringValue
TDBXInt16Value
TDBXInt32Value
TDBXInt64Value
TDBXSingleValue
TDBXDoubleValue
TDBXBcdValue
TDBXTimeValue
TDBXDateValue
TDBXTimeStampValue
TDBXBooleanValue
TDBXReaderValue
TDBXStreamValue
我们分别使用SqlServerMethod和代理类完成对服务端Hello方法的调用
SqlServerMethod.Params[ 0 ].AsString : = Name.Text;
SqlServerMethod.ExecuteMethod;
Memo.Lines.Add( ' Use SqlServerMethod: ' + SqlServerMethod.Params[ 1 ].AsString);
这里参数使用了索引值进行访问 传递的顺序是从左到右添加到Params列表 返回值是在列表的最后一个位置
同样也可以使用ParamByName(参数名称).Value的形式传递参数 返回值的名称默认是'ReturnParameter'
使用代理类调用的方法和调用本地方法区别不大 因为远程调用的具体过程已经被代理类封装
可以看下代理类中生成的Hello方法
begin
if FHelloCommand = nil then
begin
FHelloCommand : = FDBXConnection.CreateCommand;
FHelloCommand.CommandType : = TDBXCommandTypes.DSServerMethod;
FHelloCommand.Text : = ' TSM.Hello ' ;
FHelloCommand.Prepare;
end ;
FHelloCommand.Parameters[ 0 ].Value.SetWideString(Message);
FHelloCommand.ExecuteUpdate;
Result : = FHelloCommand.Parameters[ 1 ].Value.GetWideString;
end ;
我们看到代理类使用了比SqlServerMethod更低级的DBXCommand进行了封装 以更友好的方式给我们使用
begin
Memo.Lines.Add( ' Use Proxy: ' + Hello(Name.Text));
Free;
end ;
下面我们用TStream返回一个结构体并且在客户端读出
服务端部分
FirstName: array [ 0 .. 99 ] of Char;
LastName: array [ 0 .. 99 ] of Char;
end ;
function TSM.StreamMethod: TStream;
var
Name: TName;
begin
Name.FirstName : = ' 爱新觉罗 ' ;
Name.LastName : = ' 玄烨 ' ;
Result : = TMemoryStream.Create;
Result.Seek( 0 , soFromBeginning);
Result.Write(Name, SizeOf(TName));
Result.Seek( 0 , soFromBeginning); // 返回到客户端的数据是从position开始的
end ;
注意:写完数据以后需要定位到头部 否则客户端得到的数据长度为0
客户端部分
var
Name: TName;
begin
if SQLConnection.Connected then
begin
with TSMClient.Create(SQLConnection.DBXConnection) do
begin
StreamMethod.ReadBuffer(Name, SizeOf(TName));
Memo.Lines.Add(Format( ' (StreamMethod)FirstName: %s LastName: %s ' ,[Name.FirstName, Name.LastName]));
Free;
end ;
end ;
end ;
最后一个函数演示了使用var和out关键字来返回参数
以下是可以使用这两个关键字的标量值类型
boolean
SmallInt
Integer
Int64
Single
Double
AnsiString
String
TDBXTime
TDBXDate
再加上其他的参数类型
TStream
TDataSet
TParams
TDBXReader
TDBXConnection
但是在实际测试过程中发现在使用string类型做out和var的参数时 无法使用
跟踪发现源码中ansistring和string的相关代码已经被注释掉 估计是有BUG存在所以不支持 以后应该可以修复
以下摘自DSReflect单元的procedure TDSMethodValues.AssignParameterValues(Parameters: TDBXParameterArray);
// begin
// s : = Value.GetAnsiString;
// GetMem(p, SizeOf(Pointer));
// UniqueString(s);
// PPointer(p)^ : = Pointer(s);
// FMethodValues[i] : = MakeRefVar(varString, p);
// end ;
// TDBXDataTypes.BytesType:
// begin
// SetLength(bytes, value.GetValueSize);
// Value.GetBytes( 0 , bytes, 0 , Length(Bytes));
// GetMem(p, Length(bytes));
// Move(bytes[ 0 ], p^, Length(bytes));
// FMethodValues[i] : = MakeRefVar(varByte or varArray, p);
// end ;
// TDBXDataTypes.WideStringType:
// begin
// w : = Value.GetWideString;
// GetMem(p, SizeOf(Pointer));
// UniqueString(w);
// PPointer(p)^ : = Pointer(w);
// FMethodValues[i] : = MakeRefVar(varUString, p);
// end ;
贴上效果图
附上DEMO源码 DataSnapDemo_2.rar