大家好:)这是我在stackoverflow上遇到的第一个问题:)
在Delphi XE2 RTTI中,我们有TRttiMethod类,它具有函数CreateImplementation()
,该函数可动态创建具有与主体相同的签名和匿名方法的过程或函数。
使用TRttiContext.getMethods()
/getMethod()
,我们可以获得类方法的集合-TRttiMethod的集合。
文档说(http://docwiki.embarcadero.com/VCL/en/RTTI.TRttiMethod)不要直接创建TRTTiMethod,而是使用getMethods()获取其实例。
因此,如果我们有TRTTIMethod
实例,我们可以动态创建具有相同签名的方法,然后再调用它。
问题是..
例如,我们有TNotifyEvent ... TRttiContext.getType(typeinfo(TNotifyEvent))
返回TRttiType
实例对象,该对象具有typekind = tkMethod
。
我们知道TNotifyEvent的签名是对象的过程(发送者:TObject);
是否有可能为此获得TRttiMethod
?我想使用TRttiMethod.CreateImplementation()
为事件动态创建eventHandler
还是可能存在另一种动态创建方法实现的方法?
PS:想法是创建类似事件链的东西。在编译时,我们不知道事件的类型/签名,因此我们可以使用泛型,例如TEvenChain 。 Chain在已注册的事件处理程序上具有集合,因此,由于我们在编译时不知道处理程序类型,因此必须动态创建它,并且该处理程序仅获取其参数并使用它们调用已注册的处理程序。
更新:
这是一些代码(想法是创建事件处理程序链):
procedure TMainForm.FormCreate(Sender: TObject);
begin
FEventChain := TNotifyChain.Create();
FEventChain.AddHandler(event1);
FEventChain.AddHandler(event2);
TestButton.OnClick := FEventChain.EventHandler;
end;
Event1
和event2
是形式为(sender : TObject)
的方法;这不是一般示例(在这种情况下,T为NotifyEvent/TChain )
TEventChain.EventHandler
也是TNotifyEvent
TNotifyChain
是TNotifyChain = class(TObject)
strict private
FEvent : TNotifyEvent;
FItems : TList<TNotifyEvent>;
FCtx : TRttiContext;
public
procedure TestNotifyHandler(sender : TObject); virtual; abstract;
constructor Create();
procedure AddHandler(eh : TNotifyEvent);
property EventHandler : TNotifyEvent read FEvent;
end;
EventHandler
属性映射到FEvent
变量。由于我们假设事件/处理程序的类型未知,因此未分配FEvent
。因此,在构造函数中,我们使用
TNotifyEvent
签名创建虚拟方法,并将其代码分配给FEvent
:constructor TNotifyChain.Create();
var st: TRttiType;
//et : TRttiMethodType;
Callback : TMethodImplementationCallback;
rttiMethod : TRttiMethod;
m : TMethod;
mi : TMethodImplementation;
begin
inherited;
FItems := TList<TNotifyEvent>.Create();
FCtx := TRttiContext.Create();
//et := FCtx.GetType(typeinfo(TNotifyEvent)) as TRttiMethodType;
st := FCtx.GetType(self.ClassType);
rttiMethod := st.GetMethod('TestNotifyHandler');
Callback := procedure(UserData: Pointer;
const Args: TArray<TValue>;
out Result: TValue)
var i : integer;
e : TMethod;
begin
for i := 0 to FItems.Count - 1 do begin
e := TMethod(Fitems[i]);
result := Invoke(e.Code, args, rttiMethod.CallingConvention, nil);
end;
end;
mi := rttiMethod.CreateImplementation(self, Callback);
m.data := self;
m.Code := mi.CodeAddress;
FEvent := TNotifyEvent(m);
end;
在这里,我使用
TestNotifyHandler
方法使用TRttimethod.CreateImplementation()
创建具有相同签名的实际处理程序所以我想,有一种方法可以在运行时使用
TRttiMethodType
中的TNotifyEvent
创建事件处理程序的实现,因为它具有有关参数类型/计数和所用实际事件的调用约定的信息(一般情况下)。 最佳答案
类型为TRttiType
的TkMethod
将被表示为TRttiMethodType
。您不能从中获取TRttiMethod
,因为它不是方法;它不是方法。它是一个方法指针,但是如果您看一下TRttiMethodType
及其Invoke
方法,您应该找到所需的确切信息。
关于delphi - 是否可以使用TypeKind = tkMethod为TRttiType创建TRttiMethod实例?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9330541/