![]() |
Delphi-Version: 10.2 Tokyo
Event handler dynamisch setzen
Hallo,
ich möchte einen Event Handler dynamisch setzen. Der Event Handler hat dieselbe Signatur wie TNotifyEvent in dem dynamischen Coding kann ich aber nicht das Symbol "TNotifyEvent" verwenden, deshalb habe ich ein neues Symbol "TEventArgsRef" angelegt, das identisch ist. Das Beispiel ist auf ein minimum reduziert:
Delphi-Quellcode:
Der Versuch mit TValue.Make führt zu einer Speicherausnahme. Auch TValue.From funktioniert nicht,
program ex1;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.classes, Rtti; type TEventArgsRef = procedure(Sender: TObject) of object; type TWrapper = class(TObject) private public published procedure Event(Sender: TObject); end; procedure TWrapper.Event(Sender: TObject); begin writeln('Event'); end; var sl: TStringlist; Event: TEventArgsRef; value: TValue; context: TRttiContext; rttiType: TRttiType; prop: TRttiProperty; begin sl := TStringlist.Create; Event := TWrapper.Create().Event; context := TRttiContext.Create; rttiType := (context.GetType(sl.ClassType)); prop := rttiType.GetProperty(string('OnChange')); // Does not work //TValue.Make(@event, prop.PropertyType.handle, value); //prop.SetValue(sl, value); // Does also not work prop.SetValue(sl, TValue.From<TEventArgsRef>(Event)); sl.Add('foo'); end. hier kommt "Ungültige Typenumwandlung", obwohl TEventArgsRef und TNotifyEvent diesselbe Signatur haben. Gibt es einen Weg das Coding zum Laufen zu bringen, ohne im dynamischen Coding das Symbol TNotifyEvent zu benutzen? Viele Grüße André |
AW: Event handler dynamisch setzen
Warum so kompiliziert?
Delphi-Quellcode:
program ex1;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.classes; type TWrapper = class(TObject) private public published procedure Event(Sender: TObject); end; procedure TWrapper.Event(Sender: TObject); begin writeln('Event'); end; var sl: TStringlist; wrapper: TWrapper; begin wrapper := TWrapper.Create; try sl := TStringlist.Create; try sl.OnChange := wrapper.Event; sl.Add('foo'); finally sl.Free; end; finally wrapper.Free; end; end. |
AW: Event handler dynamisch setzen
Danke für die Antwort. Das Beispiel von mir ist eine starke Vereinfachung von meinem Framework,
welches über eine generische Schnittstelle (Dll) Delphi Komponenten aufrufbar macht. Daher muss jeder Zugriff komplett dynamisch über Extended Rtti erfolgen. Gibt es hier eine dynamische Lösung? Viele Grüße André |
AW: Event handler dynamisch setzen
Zitat:
Delphi-Quellcode:
Bis bald...
type
TWrapper = class(TObject) public procedure DoChange1(pmObject: TObject); procedure DoChange2(pmObject: TObject); end; procedure TWrapper.DoChange1(pmObject: TObject); begin ShowMessage('Helau!'); end; procedure TWrapper.DoChange2(pmObject: TObject); begin ShowMessage('Helau! Helau!'); end; var strList: TStringList; changeEvent: TNotifyEvent; begin var wrapper: TWrapper := TWrapper.Create; try strList := TStringList.Create; try strList.OnChange := wrapper.DoChange1; strList.Add('Test1'); var rttiType: TRttiType := TRttiContext.Create.GetType(TypeInfo(TStringList)); if rttiType <> Nil then begin var rttiProp: TRttiProperty := rttiType.GetProperty('OnChange'); if (rttiProp <> Nil) and (rttiProp.PropertyType.TypeKind = tkMethod) then begin changeEvent := wrapper.DoChange2; var eventValue: TValue; TValue.Make<TNotifyEvent>(changeEvent, eventValue); rttiProp.SetValue(strList, eventValue); strList.Add('Test2'); end; end; finally strList.Free; end; finally wrapper.Free; end; end; Thomas |
AW: Event handler dynamisch setzen
Zitat:
Delphi-Quellcode:
Bis bald...
var
strList: TStringList; changeEvent: TEventArgsRef; begin var wrapper: TWrapper := TWrapper.Create; try strList := TStringList.Create; try strList.OnChange := wrapper.DoChange1; strList.Add('Test1'); var rttiType: TRttiType := TRttiContext.Create.GetType(TypeInfo(TStringList)); if rttiType <> Nil then begin var rttiProp: TRttiProperty := rttiType.GetProperty('OnChange'); if (rttiProp <> Nil) and (rttiProp.PropertyType.TypeKind = tkMethod) then begin changeEvent := wrapper.DoChange2; var eventValue: TValue := rttiProp.GetValue(strList); TValueData(eventValue).FAsMethod.Code := TMethod(changeEvent).Code; rttiProp.SetValue(strList, eventValue); strList.Add('Test2'); end; end; finally strList.Free; end; finally wrapper.Free; end; end; Thomas |
AW: Event handler dynamisch setzen
Perfekt, vielen Dank, genau das hatte ich gesucht.
Viele Grüße André |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz