在过去客户端要调用远程服务器的方法需要通过在TLB里添加接口并且在服务器对象中实现

在DataSnap 2009中调用远程服务器的方法是基于delphi的RTTI机制的

想要一个类允许被远程调用需要做以下两点

1.把该类和DSServerClass连接在一起

procedure TMainForm.DSServerClassGetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
begin
PersistentClass := TSM;
end;

DSServerClass的OnGetClass就是用于完成此任务的

注意:DSServerClass必须设置要导出的类 否则会出现SOnGetClassNotSet的异常信息

2.该类必须使用$MethodInfo编译指令生成详细的RTTI信息

{$MethodInfo ON}
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个输出的成员函数

TSM = class(TDSServerModule)
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.ServerMethodName := 'TSM.Hello';
SqlServerMethod.Params[0].AsString := Name.Text;
SqlServerMethod.ExecuteMethod;
Memo.Lines.Add('Use SqlServerMethod: ' + SqlServerMethod.Params[1].AsString);

这里参数使用了索引值进行访问 传递的顺序是从左到右添加到Params列表 返回值是在列表的最后一个位置

同样也可以使用ParamByName(参数名称).Value的形式传递参数 返回值的名称默认是'ReturnParameter'

使用代理类调用的方法和调用本地方法区别不大 因为远程调用的具体过程已经被代理类封装

可以看下代理类中生成的Hello方法

function TSMClient.Hello(Message: string): string;
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进行了封装 以更友好的方式给我们使用

with TSMClient.Create(SQLConnection.DBXConnection) do
begin
Memo.Lines.Add('Use Proxy: ' + Hello(Name.Text));
Free;
end;

下面我们用TStream返回一个结构体并且在客户端读出

服务端部分

TName = packed record
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

客户端部分

procedure TMainForm.StreamTestClick(Sender: TObject);
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);

// TDBXDataTypes.AnsiStringType:
// 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

转载于:https://www.cnblogs.com/MaxWoods/archive/2011/09/23/2187839.html

DataSnap 2009 系列之二 (方法篇)相关推荐

  1. 速攻蓝牙NRF52832系列教程之方法篇(三)

    三.如何快速攻克一个SoC芯片     在这个讲求速度.效率的年代,慢一步就会愈发被动,错失诸多良机.     对产品研发公司来说,工程师如能迅速攻克一款更新更强的芯片,抢先发布产品,就能早一步抢占市 ...

  2. JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)

    阅读目录 七.多值输入组件manifest 1.效果展示 2.源码说明 3.代码示例 八.文本框搜索组件bootstrap-typeahead 1.效果展示 2.源码说明 3.代码示例 九.boots ...

  3. Windows系统安装及优化系列(二)在PE下安装Windows10系统以及Gho镜像的安装方法

    说实在的我也是个刚进入IT世界的小白.写这个文章系列主要是为了给一些分享一些Windows系统的安装方法,因为我经常帮同学重装系统,我就在想能不能出个教程来让他们自己动手折腾,体验一下重装系统的乐趣, ...

  4. 【阿里妈妈数据科学系列】第五篇:实验指标设定方法与指标体系构建

    ▐ 前言 在[阿里妈妈数据科学系列]前四期内容中,我们介绍了 AB TEST 的基础知识与框架及每个部分的方法论与技术,本期我们主要介绍实验指标设定方法与指标体系构建. 指标体系构建在 AB Test ...

  5. 微课系列(二):列表方法sort()和内置函数sorted()的稳定排序特点

    技术要点: 在使用列表的sort()方法或者内置函数sorted()进行排序时,可以使用key参数指定排序规则.对于排序规则没有覆盖到的元素,谁在前谁在后都是一样的.保留这些元素本来的相对顺序,这样的 ...

  6. 明翰英语教学系列之方法篇

    文章目录 传送门 前言 `学习路径&知识体系` 学习技巧 `构词规律` `词汇的偏旁部首` 词义前缀 否定前缀 `in-` mis- dis- de- un- con前缀 out前缀 sur前 ...

  7. iVX低代码平台系列详解 -- 概述篇(二)

    写在前面 ivx动手尝试电梯:ivx在线编辑器 iVX系列教程持续更新中 上篇文章可看:iVX低代码平台系列详解 – 概述篇(一) ivx目录 写在前面 一.iVX优势 1.快速学习 2.快速开发 3 ...

  8. 【冰极峰教程系列之二】:牢不可破的九宫格布局

    原创:冰极峰 转载请注明出处 时间:2009年6月22日 8:40:16 冰极峰教程系列之一:九宫格基本布局 冰极峰教程系列之二:牢不可破的九宫格布局 冰极峰教程系列之三:三层分离的完美九宫格 冰极峰 ...

  9. [转]OllyDBG 入门系列(二)-字串参考

    标 题: [原创]OllyDBG 入门系列(二)-字串参考 作 者: CCDebuger 时 间: 2006-02-14,13:34 链 接: http://bbs.pediy.com/showthr ...

最新文章

  1. 学界 | UC伯克利发布一个低成本家居机器人,会叠衣服、会泡咖啡
  2. MAC OS 10.10.5虚拟机免费下载(可安装Xcode7)
  3. 老男孩Python全栈开发(92天全)视频教程 自学笔记20
  4. 那些年,我深爱着的PPT(一)
  5. 根据文件扩展名获取系统图标
  6. sharedpreferences使用方法_细数 SharedPreferences 的那些槽点 !
  7. 宏基因组多少钱一个样_离网式光伏发电系统费用一般是多少钱
  8. 团队作业2——需求分析原型设计
  9. 让你的linux操作系统更加安全
  10. 计算机网络中的HTML,计算机网络分类有哪些
  11. 解决重装 Oracle 出现的 INS-32025 问题,完全卸载 Oracle11g
  12. Java微信公众平台开发(十五)--微信JSSDK的使用
  13. codereviw得到的一些经验
  14. 操作系统原理学习总结
  15. Mathpix Snip--图片中识别公式
  16. 每一个成年男人在算法中都是好色之徒
  17. 海思hi3518用eclipse采用交叉编译器编译程序在海思开发板上运行
  18. 百度地图SDK for Android【离线地图】
  19. Eclipse安装( jdk安装以及环境配置教程 )
  20. Linux远程和文件传输工具Xshell、Xftp使用方法

热门文章

  1. 安装server 2012 时提示输入的密码不满足网络或组管理员设置的密码复杂度
  2. Python 技术篇-用win32库实现读取、添加、修改注册表的值实例演示
  3. C# 学习笔记(5) 继承
  4. CTFshow php特性 web142
  5. sdut-3102小鑫追女神
  6. Python读文件要用到的一些东西
  7. matlab和C如何混编
  8. fullfile函数作用
  9. CalcBackProject函数
  10. integral函数