delphi - 通过 TRttiProperty.SetValue 分配对象过程时会引发 EInvalidCast 异常

标签 delphi delphi-xe2 rtti

我正在尝试使用TRttiProperty.SetValue过程通过rtti分配一个对象过程类型的属性,但是当我尝试制作时会引发此异常赋值EInvalidCast:无效的类类型转换

此示例应用程序显示了问题

{$APPTYPE CONSOLE}

uses
 Rtti,
 SysUtils;

type
  TMyCallBack = procedure (const Foo : string) of object;
  TMyClass    = class
    procedure DoSomething(const Foo: String);
  end;

  TMyAnotherClass  = class
  private
    FDoSomething: TMyCallBack;
  published
    property DoSomething : TMyCallBack read FDoSomething Write FDoSomething;
  end;

{ TMyClass }

procedure TMyClass.DoSomething(const Foo: String);
begin
  Writeln('Hello');
end;

Var
  MyClass : TMyClass;
  t       : TRttiInstanceType;
  v       : TValue;
  p       : TRttiProperty;
  Bar     : TMyCallBack;
begin
  try
    MyClass:=TMyClass.Create;
    try
      t:=TRttiContext.Create.GetType(TMyAnotherClass).AsInstance;
      v:=t.GetMethod('Create').Invoke(t.MetaclassType,[]);
      p:=t.GetProperty('DoSomething');
      Bar:=MyClass.DoSomething;
      if p<>nil then
       p.SetValue(v.AsObject, @Bar); //here the exception is raised
    finally
     MyClass.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

如何解决这个问题?

最佳答案

当我追踪到错误行时,我最终发现了隐式 TClass->TValue 转换例程。看起来 @Bar 是一个指针,编译器隐式地将其转换为 TClass,从那里开始一切都变得一团糟。这不是你想要的。

您需要的是一个类型和值与 Bar 匹配的实际 TValue。试试这个:

Var
  MyClass : TMyClass;
  t       : TRttiInstanceType;
  v       : TValue;
  p       : TRttiProperty;
  Bar     : TMyCallBack;
  vBar    : TValue;
begin
  try
    MyClass:=TMyClass.Create;
    try
      t:=TRttiContext.Create.GetType(TMyAnotherClass).AsInstance;
      v:=t.GetMethod('Create').Invoke(t.MetaclassType,[]);
      p:=t.GetProperty('DoSomething');
      Bar:=MyClass.DoSomething;
      vBar := TValue.From<TMyCallback>(bar);
      if p<>nil then
       p.SetValue(v.AsObject, vBar); //here the exception is raised
    finally
     MyClass.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

关于delphi - 通过 TRttiProperty.SetValue 分配对象过程时会引发 EInvalidCast 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10150551/

相关文章:

Delphi - 隐藏的MDI子窗体创建

Delphi FMX编辑控件不一致——如何制作快速录入表单?

delphi - 如何在运行时设计器中隐藏继承的已发布属性?

delphi - 我可以将 Delphi TEdit(或类似的)简单地连接到类的已发布属性吗?

c++ - typeid 结果不匹配

delphi - 从 Delphi 2010 IDE 打印格式化源代码

delphi - 如何检查文件是否有备用数据流?

Delphi XE2 RTTI坏了?

delphi - 如何防止 "end process tree"终止我已启动的程序?

delphi - 如何在Delphi XE2中解释.otares文件?