以前,我有一个函数可以通过RTTI获取对象属性并设置其值。现在,我决定将其拆分为TRTTI.GetObjProp
和TRTTI.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;
为什么我在使用函数时正确定义了函数结果,但是当我退出函数时却没有正确定义?
答案 0 :(得分:4)
TRttiProperty
实例归TRttiContext
对象所有。当您的局部变量ctx
离开作用域时,该TRttiContext
对象将被销毁,并带有它拥有的所有对象,包括您的TRttiProperty
实例。
您需要确保拥有使用的任何RTTI对象的TRttiContext
对象的生存时间至少与对那些拥有的对象的任何引用一样长。最简单的方法可能是使TRttiContext
对象成为全局变量。