以前我有一个函数可以通过 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;
Run Code Online (Sandbox Code Playgroud)
为什么当我在函数中时函数结果被正确定义,但当我离开函数时却没有正确定义?
实例TRttiProperty由对象拥有TRttiContext。当局部变量ctx离开作用域时,该TRttiContext对象将被销毁,并带走它拥有的所有对象,包括您的TRttiProperty实例。
您需要确保TRttiContext拥有您使用的任何 RTTI 对象的对象的生命周期至少与对这些拥有的对象的任何引用一样长。实现这一点的最简单方法可能是使TRttiContext对象成为全局变量。