gpt4 book ai didi

delphi - 是否可以使用 TypeKind=tkMethod 为 TRttiType 创建 TRttiMethod 实例?

转载 作者:行者123 更新时间:2023-12-03 14:54:07 27 4
gpt4 key购买 nike

大家好:)这是我在 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)) 返回具有 typekind = tkMethodTRttiType 实例对象。我们知道 TNotifyEvent 的签名是对象的 procedure (sender : 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;

Event1event2 是表单的方法(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()

创建具有相同签名的实际处理程序

所以我想,有一种方法可以使用来自 TNotifyEventTRttiMethodType 在运行时创建事件处理程序的实现,因为它具有有关参数类型/计数和调用约定的信息使用的实际事件(在一般情况下)。

最佳答案

类型为 TkMethodTRttiType 将表示为 TRttiMethodType。您无法从中获取 TRttiMethod,因为它不是方法;它是一个方法指针,但如果您查看 TRttiMethodType 及其 Invoke 方法,您应该准确找到您需要的内容。

关于delphi - 是否可以使用 TypeKind=tkMethod 为 TRttiType 创建 TRttiMethod 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9330541/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com