![]() |
AW: Klasseninstanz zur Laufzeit bestimmen
Hi zusammen
Sorry, wenn ich auf Sir Rufos Vorschlag bisher nicht eingegangen bin; der Grund liegt vor allem darin, dass ich bisher sehr wenig mit Generics arbeite, da ich die Dinger zu wenig durchschaue. Eigentlich ist die einzige generische Klasse, die ich bisher benutze, eine Objectliste, die mir einst DeddyH vorgeschlagen hat. Ein weiterer seiner Vorschläge betraf die Verwendung einer ![]()
Delphi-Quellcode:
Meinen Frames muss ich dann noch folgendes verpassen:
uses Generics.Collections, Vcl.Forms, System.Classes, System.SysUtils;
type EFrameNotRegistered = class(Exception); TFrameClass = class of TFrame; TFrameFactory = class abstract strict private class var FAssociations: TDictionary<string, TFrameClass>; class constructor Create; class destructor Destroy; public class procedure RegisterFrameClass(const Extension: string; FrameClass: TFrameClass); class function GetRegisteredFrameClass(const Extension: string; AOwner: TComponent): TFrame; end; implementation { TFrameFactory } class constructor TFrameFactory.Create; begin FAssociations := TDictionary<string, TFrameClass>.Create; end; class destructor TFrameFactory.Destroy; begin FAssociations.Free; end; class function TFrameFactory.GetRegisteredFrameClass(const Extension: string; AOwner: TComponent): TFrame; var AFrameClass: TFrameClass; //TCustomFrameClass begin if FAssociations.TryGetValue(AnsiLowerCase(Extension), AFrameClass) then Result := AFrameClass.Create(AOwner) else raise EFrameNotRegistered.CreateFmt('Für die Endung %s ist keine Frameklasse registriert.', [Extension]); end; class procedure TFrameFactory.RegisterFrameClass(const Extension: string; FrameClass: TFrameClass); begin FAssociations.AddOrSetValue('.' + AnsiLowerCase(Extension), FrameClass); end; end.
Delphi-Quellcode:
Dein Vorschlag ist offenbar das generische Gegenstück zu dieser Fabrikklasse, und wenn mich meine bisherigen Kenntnisse der Generics nicht täuschen, könnte ich da jede Klasse registrieren, die, in deinem Beispiel, von TFoo, bzw. TBar erbt oder selbst von einem dieser Typen ist.
initialization
TFrameFactory.RegisterFrameClass('css', TCSSFrame); Somit könnte ich da jeden meiner Eventhandler registrieren. Hab ich das richtig verstanden? Gruss Delbor |
AW: Klasseninstanz zur Laufzeit bestimmen
Genau so isses :)
|
AW: Klasseninstanz zur Laufzeit bestimmen
Hi zusammen
Wie man nur so blind sein kann!! Nochmal zur Erinnerung die CreateAufrufe und die Createprozedur selbst:
Delphi-Quellcode:
Damit wird bei jedem Aufruf eine Instanz der Klasse TAttributsClass erzeugt und nicht eine Klasseninstanz FCommentAttri - somit kann ich auch nicht auf eine Instanz FCommentAttri zugreifen. Einfach, nicht?
constructor TJavaScriptAttriTLBXFrame.Create(AOwner: TComponent);
begin inherited; FJavaScriptAttributsList := TDataObjectList<TAttributsClass>.Create(); FJavaScriptAttributsList.OwnsObjects := True; CreateAttribute(FCommentAttri, 'Kommentare', 'FCommentAttri'); // fCommentAttri: TSynHighlighterAttributes; CreateAttribute(FIdentifierAttri, 'Bezeichner', 'FIdentifierAttri'); // fPropertyAttri: TSynHighlighterAttributes; CreateAttribute(FKeyAttri, 'Schlüsselworte', 'FKeyAttri'); // fKeyAttri: TSynHighlighterAttributes; CreateAttribute(FNonReservedKeyAttri, 'Nicht reservierte Schlüssel', 'FNonReservedKeyAttri'); // fSpaceAttri: TSynHighlighterAttributes; CreateAttribute(FEventAttri, 'Ereignisse', 'FEventAttri'); // fStringAttri: TSynHighlighterAttributes; CreateAttribute(FNumberAttri, 'Zahlen', 'FNumberAttri'); // fNumberAttri: TSynHighlighterAttributes; CreateAttribute(FSpaceAttri, 'Leerzeichen', 'FSpaceAttri'); // fColorAttri: TSynHighlighterAttributes; CreateAttribute(FStringAttri, 'Strings', 'FStringAttri'); // fTextAttri: TSynHighlighterAttributes; CreateAttribute(FSymbolAttri, 'Symbole', 'FSymbolAttri'); // fSymbolAttri: TSynHighlighterAttributes; end; destructor TJavaScriptAttriTLBXFrame.Destroy; begin FJavaScriptAttributsList.Free; inherited; end; procedure TJavaScriptAttriTLBXFrame.CreateAttribute(var AAttrib: TAttributsClass; const AName: string; AInstanz : String); begin AAttrib:= TAttributsClass.Create(Self); AAttrib.AttributName := AName; AAttrib.InstanzName := AInstanz; FJavaScriptAttributsList.Add(AAttrib); CmbxAttributes.Items.AddObject(AName,TObject(AAttrib)); Application.ProcessMessages; end; Um die richtigen Instanzen zu erzeugen, müsste ich wohl eher so etwas macen:
Delphi-Quellcode:
Wobei dies auch nicht ganz stimmt: Der rechte Teil muss ein Klassenbezeichner sein - der muss aber zum Instanzbezeichner passen. Das property Instanzname ist auch nicht das gelbe vom Ei...
procedure TJavaScriptAttriTLBXFrame.CreateAttribute(var AAttrib: TAttributsClass; const AName: string; AInstanz : String);
begin AAttrib:= AAttrib.Create(Self); AAttrib.AttributName := AName; AAttrib.InstanzName := AInstanz; FJavaScriptAttributsList.Add(AAttrib); CmbxAttributes.Items.AddObject(AName,TObject(AAttrib)); Application.ProcessMessages; end; Das heisst nichts anderes, als dass es einige von TAttributsClass abgeleitete Klassen geben wird, wie zum Beispiel TCommentAttri. Die Erzeugung ist dann:
Delphi-Quellcode:
Damit habe ich ohne Verrenkungen zugriff auf die richtige Instanz.
FCommentAttri:= TCommentAttri.Create
Gruss Delbor |
AW: Klasseninstanz zur Laufzeit bestimmen
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen
Die Idee aus meinem vorigen Beitrag war wirklich nicht schlecht - sie liefert eine Antwort auf die Frage, die der Threadtitel vorgibt - aber sie ist noch weniger das Gelbe vom Ei, wie das Property 'InstanzName' der Klasse TAttributsClass, da sie zu einem, wie ich meine, ziemlich seltsamen Konstrukt führt:
Delphi-Quellcode:
Dabei führen die von TAttributsClass abgeleiteten Klassen keinerlei neue Member ein, weder Eigenschaften Methoden oder Ereignisse - wobei ich mir schon überlegt habe, ob die Dinger nicht selbst ein Event abfeuern könnten...
TAttributsClass = Class(TPersistent)
public BackGround : TColor; ForeGround : TColor; StyleBold: Boolean; StyleItalic : Boolean; StyleUnderLine : Boolean; StyleStrikeOff : Boolean; AttributName: String; InstanzName: String; Constructor Create(AOwner: TComponent); Destructor Destroy; override; end; TJavaScriptCommentClass = Class(TAttributsClass); TJavaScriptIdentifierClass = Class(TAttributsClass); TJavaScriptKeyClass = Class(TAttributsClass); TJavaScriptNonReservedKeyClass = Class(TAttributsClass); TJavaScriptEventClass = Class(TAttributsClass); TJavaScriptNumberClass = Class(TAttributsClass); // TJavaScriptSpaceClass = Class(TAttributsClass); TJavaScriptStringClass = Class(TAttributsClass); TJavaScriptSymbolClass = Class(TAttributsClass); Aber ich habe etwas viel besseres ![]() Ein Test in einem meiner Synedit-Frames brachte das gewünschte Resultat, ersichtlich im angehängten Jpeg:
Delphi-Quellcode:
Wie der Anhang zeigt, liefert mir das alle Propertys als String. Um meine neuen Einstellungen aus meinem Frame richtig zuordnen zu können, brauche ich entweder einen Kalssenbezeichner, der dem Probertynamen entspricht oder einen String, den ich mitt dem als String vorliegenden Propertynamen vergleichen kann.
procedure TCSSFrame.SynEdit1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); var LContext: TRttiContext; LType: TRttiType; LProperty: TRttiProperty; LMethod: TRttiMethod; LField: TRttiField; begin if Self.SynEdit1.SelText <> '' then begin Label1.Caption := SynEdit1.SelText; Label1.Caption := Label1.Caption + ' SynEdit1.TabWidth := '+ IntToStr(SynEdit1.TabWidth); if assigned(FOnSelectText) then // Dieser Event wird gefeuert, FOnSelectText(Self); // wenn Text markiert wird. end; LContext := TRttiContext.Create; try LType := LContext.GetType(TSynCssSyn); SynEdit1.lines.Add(LType.ToString); for LProperty in LType.GetProperties do begin SynEdit1.lines.Add (LProperty.ToString); end; finally LContext.Free; end; end; Natürlich muss ich aus der sich ergebenden Liste noch den (Teil-)String filtern, den ich in TAttributsClass.Instanzname übergebe. Aber das dürfte wohl kaum ein Problem sein. Ein weiterer Effekt: Ich brauche zur Übergabe noch genau einen Eventtyp. Oder gibts noch eine bessere Lösung? Gruss Delbor |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:05 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