以前,我有一个函数可以通过RTTI获取对象属性并设置其值。现在,我决定将其拆分为TRTTI.GetObjPropTRTTI.SetObjPropValue,以便缓存TRTTI.GetObjProp返回的值并加速数据处理。

之后发生奇怪的事情。首先,我突然注意到ctx.GetType可以正常工作,尽管我从未初始化ctx变量。好吧,如果我使用TRttiContext.Create()对其进行初始化,那么第二个怪异度将保持不变:

我调用TRTTI.GetObjProp函数,只要在这个函数中,就定义了Result,并且可以使用调试器请求它的属性。当我退出该函数时,我尝试请求rprop变量的相同属性并出现访问冲突错误。根据调试器,定义了rprop

procedure TConfManager._setValue(indicator: TComponent; name: string; value: OleVariant);
var
  rprop: TRttiProperty;
begin
  rprop := TRTTI.GetObjProp(indicator, name);
  //Access violation here when I try to use rprop
  TRTTI.SetObjPropValue(indicator, rprop, value);
end;

class function TRTTI.GetObjProp(obj: TObject; propName: string): TRttiProperty;
var
  ctx: TRttiContext;
  rtyp: TRttiType;
begin
  if obj = nil then Exit(nil);
  rtyp := ctx.GetType(obj.ClassType);
  Result := rtyp.GetProperty(propName);
end;


为什么在使用函数时正确定义了函数结果,而退出函数时却没有正确定义?

最佳答案

TRttiProperty实例归TRttiContext对象所有。当局部变量ctx离开作用域时,该TRttiContext对象将被销毁,并带有它拥有的所有对象,包括您的TRttiProperty实例。

您需要确保拥有使用的任何RTTI对象的TRttiContext对象的生存时间至少与对这些拥有对象的任何引用一样长。最简单的实现方法可能是使TRttiContext对象成为全局变量。

10-04 14:54