红鱼儿

Delphi revelations #1 – kbmMW Smart client on NextGen (Android) – Scope problems

Delphi 启示 #1 – kbmMW Smart client on NextGen (Android) – 作用域问题

以更高级的方式使用kbmMW smart client,在Android设备上,我遇到了问题。

通过继承TInvokeableVariantType,kbmMW smart client可以使用Delphi支持的特殊类型的自定义Variant,从而可以写在项目中不存在的过程/方法/函数的调用代码。

这是一种很好的方法,允许使用几乎正常的Delphi语法直接“嵌入”脚本功能,或者在kbmMW的情况下允许调用服务器端方法而不必编写stub/skeleton代码。

以下代码是从kbmMW客户端到kbmMW服务器中的服务(someservice)的调用。该调用接受4个参数,一个ID(字符串),一个整数(100)和两个通用TObjectLists(x.List1和x.List2)。

使用TInvokableVariantType的一个注意事项是,只能使用可存储在变体中的参数。所有常规类型,整数,int64,字符串,浮点数等都可以使用,但是不做转换的情况下,对象是不能自动传递。在这种情况下,使用Use.AsVariant(...)语法返回一种特殊类型的Variant变量,kbmMW就神奇的将对象实例“转换”为自定义Variant类型,同时,该类型也支持控制对象的所有权。

这些在所有平台上都可以正常工作......只要参数列表中使用Use.AsVariant即可。

在Android上(我一般假设是NextGen),变量在实际调用之前被释放,因此使保存相关数据的记录结构的内容无效,运行时抛出“Invalid variant type”异常。

var
   cli:IkbmMWSmartClient;
begin
     cli:=TkbmMWSmartRemoteClientFactory.GetClient(transport,'someservice');
 
     cli.Service.SomeMethod(x.ID,100,Use.AsVariant(x.List1,false),Use.AsVariant(x.List2,false));
...
end;

这该怎么办呢?方法有多个...其中一个是将List1和List2组合在一个对象中并发送他到服务端......但是这需要服务端也要更新,以支持接收这个组合对象。

幸运的是,还有一种更简单的解决方案:

var
   cli:IkbmMWSmartClient;
   v1,v2:variant
begin
     cli:=TkbmMWSmartRemoteClientFactory.GetClient(transport,'someservice');
 
     v1:=Use.AsVariant(x.List1,false);
     v2:=Use.AsVariant(x.List2,false);
     cli.Service.SomeMethod(x.ID,100,v1,v2);
...
end;

将变量定义为局部变量,以防止编译器过早释放variant变量的值。现在,在NextGen上一切正常。

如何在客户端与服务端传输对象,请参考xalion写的:kbmmw中向服务器端传递对象的一种简单方式。

 

posted on 2018-08-22 11:45  红鱼儿  阅读(830)  评论(0编辑  收藏  举报