开发者

How to use TValue.AsType<TNotifyEvent> properly?

I'm trying to use RTTI to add an event handler to a control, that may already have an event handler set. The code looks something like this:

var
  prop: TRttiProperty;
  val: TValue;
begin
  prop := FContext.GetType(MyControl.ClassInfo).GetProperty('OnChange');
  val := prop.GetValue(MyControl);
  FOldOnChange := val.AsType<TNotif开发者_JS百科yEvent>;
  prop.SetValue(MyControl, TValue.From<TNotifyEvent>(self.MyOnChange));
end;

I want this so I can do this in MyOnChange:

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

Unfortunately, the compiler doesn't seem to like the line FOldOnChange := val.AsType<TNotifyEvent>;. It says

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

Anyone know why that is or how to fix it? It looks right to me...


FOldOnChange is of a method pointer type, while AsType<TNotifyEvent> is a method. The compiler thinks you're trying to assign the method to the method pointer. The solution is to append () to the method call to force it, and use the return value of the method as the value to assign to FOldOnChange.

Here's a complete example:

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.


The new RTTI introduced in 2010 is basically just an advanced wrapper around the older TypInfo RTTI (for now). In TypInfo, event handlers are represented by the TMethod record. Try this (untested):

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜