Delphi反射传入var形式的参数

在反射调用方法时,常常会遇到var或out形式的参数,但是Delphi的ObjAuto单元却是不支持如此做的,因此,需要对反射的单元做一些修改,以使其支持var类型的参数

对于var和out两种类型,在Delphi的编译器看来,它们的处理是一样的,只不过out参数会在传入时,先进行一次clear操作。但是其本质还是var,因此,我们将这两种形式的参数放在一起讨论。

从CodeGear提供的ObjAuto.pas中,能够找到这么一句话, For pfVar, the variant must be a byref and equal to the type . 意思即是说,对于var型的参数,必须传入引用,由此,用一个简单的指针操作,把变量变为引用即可。

function  Reference( const  V: Variant; VarTyp: TVarType): Variant;
var
vType: TVarType;
begin
if  VarIsByRef(V)  then
    Result := V
else if  VarIsArray(V, False)  then
    Result := VarArrayRef(V)
else
begin
    VarClear(Result);
    vType := VarTyp;
     if  vType  in  [varSmallint, varInteger, varSingle, varDouble,
       varCurrency, varDate, varOleStr, varDispatch,
       varError, varBoolean, varUnknown,
       varShortInt, varByte ,varWord, varLongWord, varInt64]  then
      TVarData(Result).VType := vType or varByRef
     else
      TVarData(Result).VType := varInteger or varByRef;
    TVarData(Result).VPointer := @TVarData(V).VPointer;
end ;
end ;

通过这个函数,就可以把一个变量,变成变量的引用。当然了,有了引用之后,我们需要解引用
用一个功能相反的函数即可:

function  Unreference( const  V: Variant; VarTyp: TVarType): Variant;
var
vValue: Variant;
begin
if not  VarIsByRef(V)  then
    Result := V
else
begin
    VarClear(vValue);
    TVarData(vValue).VType := VarTyp;
    TVarData(vValue).VPointer := Pointer((TVarData(V).VPointer)^);
    Result := vValue;
end ;
end

然后还需要修改一下ObjAuto.pas
把里面的 For pfVar, the variant must be a byref and equal to the type. 下面的两行代码注释掉,也就是不进行var或out的校验

这样,我们的准备工作就完成了,下面就是用一个实例来试试var的调用。

首先做一个测试类,里面包含一个带有var参数的方法
如: procedure  TestVar(AName:  string ; AInt: integer;  var  a:  string var  b: integer);

然后按以下方式调用之:

var
v1 :  string ;
v2: integer;
vref1: Variant;
vref2: variant;
vRet: Variant;
begin
v1 := 'Test Str';
v2 := 123;
// 变量转换成引用
vref1 := Reference(v1, varString);
vref2 := Reference(v2, varInteger);
// 获取方法的反射信息
mi := GetMethodInfo(FInstance, 'TestVar');
// 调用方法,调用时传入变量的引用
ObjectInvoke(FInstance, mi, [1,2,3,4], ['1111',999, vRef1, vref2]);
// 解引用
vRet := Unreference(vref1, varString);
ShowMessage(vRet);
vRet := Unreference(vref2, varInteger);
ShowMessage(vRet);
end ;

以上例子中,传入的变量引用,在被操作后,依然以引用的形式传了回来
通过解引用的操作即可得到它的值。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值