使用 RTTI 获取/设置子属性

2023-12-02

给出下面的代码片段,使用GetPropValue(MyComponent,'MySubComponent.Prop1')引发 EPropertyError 异常。 如何使用 GetPropValue / SetPropValue 检索或设置 SubProperties 的值?

Type
  TMySubComponent = class(TInterfacedPersitent)
  private
    FProp1: Integer;
  published
    property Prop1: integer read FProp1 write FProp1;
  end;

  TMyComponent = class(TCompoent)
  private
    FMySubComponent : TMySubcomponent; 
  published
    property MySubComponent: TMySubComponent read FMySubComponent write FMySubComponent ;
  end;

正如 Robert 所说,不支持点符号,但您可以轻松创建一个函数来使用 RTTI 设置或获取子属性值。检查这个样本

{$APPTYPE CONSOLE}

uses
  Rtti,
  Classes,
  SysUtils;


Type
  TMySubComponent = class(TInterfacedPersistent)
  private
    FProp1: Integer;
  published
    property Prop1: integer read FProp1 write FProp1;
  end;

  TMyComponent = class(TComponent)
  private
    FMySubComponent : TMySubcomponent;
  published
    property MySubComponent: TMySubComponent read FMySubComponent write FMySubComponent ;
  end;



procedure SetObjValueEx(const ObjPath:string;AInstance:TObject;AValue:TValue);
Var
 c            : TRttiContext;
 Prop         : string;
 SubProp      : string;
 pm           : TRttiProperty;
 p            : TRttiProperty;
 Obj          : TObject;
begin
 Prop:=Copy(ObjPath,1,Pos('.',ObjPath)-1);
 SubProp:=Copy(ObjPath,Pos('.',ObjPath)+1);
 c := TRttiContext.Create;
 try
   for pm in c.GetType(AInstance.ClassInfo).GetProperties do
   if CompareText(Prop,pm.Name)=0 then
   begin
     p := c.GetType(pm.PropertyType.Handle).GetProperty(SubProp);
      if Assigned(p) then
      begin
        Obj:=pm.GetValue(AInstance).AsObject;
        if Assigned(Obj) then
          p.SetValue(Obj,AValue);
      end;
      break;
   end;
 finally
   c.Free;
 end;
end;


function GetObjValueEx(const ObjPath:string;AInstance:TObject):TValue;
Var
 c            : TRttiContext;
 Prop         : string;
 SubProp      : string;
 pm           : TRttiProperty;
 p            : TRttiProperty;
 Obj          : TObject;
begin
 Prop:=Copy(ObjPath,1,Pos('.',ObjPath)-1);
 SubProp:=Copy(ObjPath,Pos('.',ObjPath)+1);
 c := TRttiContext.Create;
 try
   for pm in c.GetType(AInstance.ClassInfo).GetProperties do
   if CompareText(Prop,pm.Name)=0 then
   begin
     p := c.GetType(pm.PropertyType.Handle).GetProperty(SubProp);
      if Assigned(p) then
      begin
        Obj:=pm.GetValue(AInstance).AsObject;
        if Assigned(Obj) then
          Result:=p.GetValue(Obj);
      end;
      break;
   end;
 finally
   c.Free;
 end;
end;

Var
  MyComp : TMyComponent;
begin
  try
     MyComp:=TMyComponent.Create(nil);
     try
       MyComp.MySubComponent:=TMySubComponent.Create;
       //Set the value of the property 
       SetObjValueEx('MySubComponent.Prop1',MyComp,777);
       //Get the value of the property 
       Writeln(Format('The value of MySubComponent.Prop1 is %d',[GetObjValueEx('MySubComponent.Prop1',MyComp).AsInteger]));
     finally
       MyComp.Free;
     end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 RTTI 获取/设置子属性 的相关文章

  • 防止多个实例 - 但还要处理命令行参数?

    我正在从我的应用程序处理与 Windows 相关的扩展文件 因此 当您在 Windows 中双击文件时 它将执行我的程序 然后我从那里处理该文件 如下所示 procedure TMainForm FormCreate Sender TObj
  • 通过套接字发送动态数组(在记录内)?

    我正在尝试直接使用 SendBuf 将记录从服务器传输到客户端 但是 该记录有一个动态数组的成员 并且我在某处 在 SOF 中 读到 发送记录时 成员必须是静态的 固定长度 但问题是 我无法确定如何我会 将来 发送许多论点 我怎么解决这个问
  • 从 Delphi VCL 样式获取特定字形

    我想从 VCL 样式获取特定的位图 并将其设置为按钮上的图像 它实际上是帮助问号 在位图样式编辑器中是来自表单的 btnHelp 图像 要从 VCL 样式获取视觉元素 字形 您必须使用GetElementDetails和TCustomSty
  • 如何从该 JAVA 文件中提取 Delphi 类以与 Android 一起使用?

    我的Delphi XE7项目需要与FTDI FT311 Android 配件芯片 http www ftdichip com Products ICs FT311D html 他们帮助提供了一个 Android 演示 其中包括他们的 JAV
  • 阻止 IDE 自动添加使用单位

    我正在将 Lazarus 项目转移到德尔福西雅图 Lazarus 项目依赖于 40 多个单元 包括控件 并具有多种应用程序 在所有项目的使用条款中 他们使用了以下内容 uses Classes SysUtils Forms Controls
  • 从其可执行文件的路径获取服务名称

    我有一个可执行文件的路径 它是一个正在运行的服务应用程序 例如 C Program Files x86 Someapp somesvc exe 我想停止并启动它 为此我想我需要获取服务的名称 如下所示 this https stackove
  • Delphi 中表单分发与其生命周期相关的接口对象的安全方法?

    我有一个 Delphi 表单 它提供接口对象背后的功能 代码的其他部分也通过属于该表单的属性获取引用 我无法将接口功能委托给子对象 因为太多的功能是由表单上的控件 组件提供的 我无法使用 TAggregateObject 或 TContai
  • Delphi 的内存分析工具?

    我建立了一个项目并运行它 然后在 Process Explorer 中查看它 结果发现它在启动时使用的 RAM 比我想象的要多 5 倍 现在 如果我的程序运行得太慢 我会将其连接到分析器并让它告诉我什么正在使用我的所有周期 有没有类似的工具
  • Delphi 7 - 处理表单中嵌入框架的 MouseWheel 事件?

    你好 我有一个表格 里面有几个框架 对于某些框架 我希望滚动内容 或至少处理鼠标滚轮事件 我已经尝试过以下方法 只需为每个帧分配一个 OnMouseWheel 事件处理程序 重写父窗体的 MouseWheel 事件 procedure TF
  • TFrame继承重构

    我提出的另一个 TFrame IDE 注册组件问题 感谢各位程序员的帮助 尝试 Darrian 的 TFrame 继承建议here https stackoverflow com questions 382562 delphi visual
  • MainFormOnTaskbar + 工具提示导致焦点窃取

    我使用 Delphi XE2 构建了下面的代码 它创建 Form1 Form1 立即创建 Form2 的实例 当我按下 Form2 上的按钮时 会创建第二个 Form2 现在 如果我将鼠标悬停在第二个 最上面的 Form2 上的按钮上 并等
  • 使用 TArray 而不是 Array of T 的原因是什么?

    我正在将遗留的 Delphi 应用程序迁移到 Delphi XE2 我想知道是否有充分的理由替换定义为的数组Array of MyType to TArray
  • 在网格上拖动时拖动图像更改

    我正在 StartDrag 上创建自定义 DragObject 的实例 procedure TForm1 GridStartDrag Sender TObject var DragObject TDragObject begin DragO
  • 使用远程数据编写 Android、iPad、iPhone 客户端的技术

    我需要探索世界 你写了一个杀手级应用程序 但你有 Android iPhone iPad 客户端吗 我的问题是 1 向这些设备发送数据的最佳方式是什么 按照建议进行肥皂和休息here https stackoverflow com ques
  • Delphi 应用程序被 Google Chrome 视为“危险”

    我经常用Delphi 2009制作数学软件 并将其发布在我的网站上 然而 去年左右 Google Chrome 开始认为我的一小部分 但数量不断增加 EXE 是 有害的 并且 Google Chrome 拒绝下载它们 例如 今天我编写了一个
  • Soap Delphi 客户端因 1MB 调用超时而结束

    我们正在开发 SOAP Web 服务 Apache PHP 所有小规模调用都运行良好 但对于 1Mb 的 Soap 调用 HTTPS 调用大小为 1MB 我们的 Delphi Soap 客户端在除一台 PC 之外的所有 PC 上都因超时而停
  • 如何使用 IdTCPClient 等待来自服务器的字符串?

    我的 IdTelnet indy 10 1 有问题 我无法以 Unicode 模式从服务器读取数据 现在我想用 IdTCPClient 编写 telnet 终端 服务器有时发送一行 有时发送越来越多的行 但发送之间没有固定的时间 现在我的问
  • 是否可以在虚拟树视图中选择多个列?

    我需要添加功能来复制节点和列的矩形选择 但我找不到任何方法来实际选择虚拟树视图中的多个列 除了 toFullRowSelect 之外 我只是错过了什么吗 如果没有 是否有一个后代具有类似网格的多列选择支持 经过一些测试后 我得出了以下结论
  • Delphi XE5 FireDAC 错误:无法加载供应商库 [libmysql.dll 或 libmysqld.dll]

    我在 Windows 7 64 位上使用 Delphi XE5 只是尝试 FireDAC 组件 我正在使用一个 TFDConnection 组件连接到本地 MySQL 数据库 v5 6 15 我已经将 libmysql dll 32位 v5
  • 在 tlistbox 中绘制缩略图

    在 DelphiXE 中 我使用 tFileOpenDialog 选择一个文件夹 然后在 tListBox 中列出该文件夹中的所有 jpg 文件 我允许将列表项拖放到列表中进行自定义排序 以便稍后按顺序显示它们 我希望能够在文件名旁边绘制图

随机推荐