RTTI-Fehler bei DSharp
Hallo zusammen.
Ich nutze schon seit längerem DSharps TEvent<T> bzw. IEvent<T> um mir eine Art Observer zu basteln. Das hat bisher gut geklappt. Bei einer Logging-Funktion bekomme ich aber eine EAssertViolation: "TLogFunc must contain extended RTTI (DSharp.Core.Events.pas:346)". Kann mir jemand weiterhelfen, was das Problem ist. Die Methode sieht eigentlich recht harmlos aus:
Code:
procedure TMGMain.LogFunc(S: string; Args: array of const);
begin Logbook.Lines.Add(Format(S, Args)); end; |
AW: RTTI-Fehler bei DSharp
Arrrgh, manchmal .. wirklich manchmal ... :evil:
Für alle die über sowas stolpern: Für
Code:
- Parameter (wie man sie an die Format-Funktion füttert) werden keine RTTI-Daten erzeugt. Ergo kann ich diese nicht mit DSharp nutzen. Es gibt natürlich einen QC-Eintrag dafür, was aber auch nicht weiterhilft (ich nutze XE2 - da wird sicher nix gepatcht. Wäre ja zu schön). QualityCentral-Link
array of const
Wenn jemand eine andere Art kennt, die man ähnlich leicht benutzen kann für den Aufruf, bin ich ganz Ohr. Edit:
Code:
geht auch nicht (entspricht ja mehr oder weniger dem internen
array of TVarRec
Code:
array of const
|
AW: RTTI-Fehler bei DSharp
Ich würde das wie folgt lösen:
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, RTTI, DSharp.Core.Events, DSharp.Core.Reflection; type {$M+} TTestEvent = reference to procedure(S: string; const Args: TArray<TValue>); {$M-} TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private FTestEvent: Event<TTestEvent>; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function Format(const Format: string; const Args: array of TValue): string; begin Result := System.SysUtils.Format(Format, TValue.ToVarRecs(Args)); end; procedure LogMessage(const AText: string; const AValues: array of TValue); var Values: TArray<TValue>; begin Form1.FTestEvent.Add( procedure(S: string; const Args: TArray<TValue>) var LMessage: string; begin LMessage := Format(S, Args); Form1.Memo1.Lines.Add(LMessage); end); Values := TArrayHelper.Copy<TValue>(AValues); Form1.FTestEvent.Invoke(AText, Values); end; procedure TForm1.Button1Click(Sender: TObject); begin LogMessage('message: %s %d', ['test', 1234]); end; end. |
AW: RTTI-Fehler bei DSharp
Sehr schöne Lösung - genau so werde ich es wohl lösen.
Danke :thumb: (schade, dass man Beiträge nicht upvoten kann ;-) ) |
AW: RTTI-Fehler bei DSharp
Seit r595 kannst du auch folgendes machen:
Delphi-Quellcode:
Du musst dann allerdings die Instanz selber erstellen und kannst nicht das automatische Initialisieren über den Recordtyp Event<T> benutzen.
type
TLogEvent = class(TEventBase<TLogFunc>) protected function GetInvoke: TLogFunc; override; // optional procedure InitInvoke; override; procedure InternalInvoke(s: string; Args: array of const); end; function TLogEvent.GetInvoke: TLogFunc; begin // durch das Überschreiben dieser Methode gewinnst du etwas Performance, // da nicht mehr die generische Implementierung benutzt werden muss Result := InternalInvoke; end; procedure TLogEvent.InitInvoke; begin SetInvoke(@TLogEvent.InternalInvoke); end; procedure TLogEvent.InternalInvoke(s: string; Args: array of const); var i: Integer; begin if FEnabled then for i := 0 to Count - 1 do Handler[i](s, Args); end; Für die Zukunft ist geplant, dass man eigene Klassen registrieren kann, welche dann bei Benutzung des Recordtyps erstellt werden (im
Delphi-Quellcode:
).
Event<T>.Initialize
Somit kann man für bestimmte Signaturen, selbst eine Event Klasse erstellen, die dann auch über weniger Overhead durch die generische Implementierung verfügt und somit performanter ist. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz