delphi - 如何正确使用 TValue.AsType<TNotifyEvent>?

标签 delphi delphi-2010 rtti

我正在尝试使用 RTTI 将事件处理程序添加到控件,该控件可能已经设置了事件处理程序。代码看起来像这样:

var
  prop: TRttiProperty;
  val: TValue;
begin
  prop := FContext.GetType(MyControl.ClassInfo).GetProperty('OnChange');
  val := prop.GetValue(MyControl);
  FOldOnChange := val.AsType<TNotifyEvent>;
  prop.SetValue(MyControl, TValue.From<TNotifyEvent>(self.MyOnChange));
end;

我想要这个,这样我就可以在 MyOnChange 中执行此操作:

begin
  if assigned(FOldOnChange) then
    FOldOnChange(Sender);
  //additional code here
end;

不幸的是,编译器似乎不喜欢 FOldOnChange := val.AsType<TNotifyEvent>; 行。它说

E2010 Incompatible types: 'procedure, untyped pointer or untyped parameter' and 'TNotifyEvent'

有人知道这是为什么或者如何解决吗?我觉得很合适...

最佳答案

FOldOnChange是方法指针类型,而AsType<TNotifyEvent>是一种方法。编译器认为您正在尝试将该方法分配给方法指针。解决方案是附加 ()到方法调用来强制它,并使用方法的返回值作为分配给 FOldOnChange 的值.

这是一个完整的示例:

uses SysUtils, Rtti;

type
  TEv = procedure(Sender: TObject) of object;

  TObj = class
  private
    FEv: TEv;
  public
    property Ev: TEv read FEv write FEv;
    class procedure Meth(Sender: TObject);
  end;

class procedure TObj.Meth(Sender: TObject);
begin
end;

procedure P;
var
  ctx: TRttiContext;
  t: TRttiType;
  p: TRttiProperty;
  v: TValue;
  o: TObj;
  e: TEv;
begin
  t := ctx.GetType(TObj);
  p := t.GetProperty('Ev');
  o := TObj.Create;
  try
    // Set value explicitly
    o.Ev := TObj.Meth;
    // Get value via RTTI
    v := p.GetValue(o);
    //e := v.AsType<TEv>; // doesn't work
    e := v.AsType<TEv>(); // works
  finally
    o.Free;
  end;
end;

begin
  try
    P;
  except
    on e: Exception do
      Writeln(e.Message);
  end;
end.

关于delphi - 如何正确使用 TValue.AsType<TNotifyEvent>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2419552/

相关文章:

delphi - 为什么 "The Tomes of Delphi"处的代码无法编译?

delphi - 如何使用Delphi RTTI获取和设置记录值

visual-studio - 是否允许在禁用 rtti 的应用程序中链接启用 rtti 的 DLL?

Delphi文件目录选择(来自DLL)将其他窗口带到当前应用程序前面?

delphi - Delphi中有HashSet吗?

delphi - 如何使过程更改变量参数的值?

delphi - TShellChangeThread 中的内存泄漏

delphi - 在网格上拖动时拖动图像更改

Delphi:使用 RTTI 实例化的对象未调用重写方法

delphi - 如何检测滚动条是否在最底部?