![]() |
Delphi-Version: XE7
Anonyme Methoden in Attributen
Hallo,
Das scheint leider nicht zu gehen:
Delphi-Quellcode:
Das finde ich schade und ich wäre froh wenn Embarcadero sowas implementieren könnte.
TAnonym = reference to procedure;
TMyCustomAttribute = class(TCustomAttribute) constructor Create(Anonym: TAnonym); // compiliert end; // Funktioniert nicht: "Konstantenausdruck erwartet" [TMyCustomAttribute( procedure begin ShowMessage('Test'); end) ] TTestclass = class end; Denn ich finde dass der Ausdruck konstant genug ist. Ansonsten: Kennt jemand eine Alternative? |
AW: Anonyme Methoden in Attributen
Bei anonymen Methoden wird zur "Laufzeit" ein Interface erstellt und du kannst dort nur Konstanten verwenden.
|
AW: Anonyme Methoden in Attributen
Die Alternative heißt: neue Attribute Klasse, und dort den Code implementieren.
|
AW: Anonyme Methoden in Attributen
Spannend. Hab gar nicht geahnt, dass so etwas geht. Wann genau wird der Code dann ausgeführt? Einmalig, zur Initialisierung oder immer, wenn auf das Attribut zugegriffen wird? Spontan fällt mir kein Use Case ein, aber das heisst ja nix :lol:
|
AW: Anonyme Methoden in Attributen
Zitat:
Zitat:
In dieser Hinsicht ist Delphi übrigens mal ausnahmsweise C# nicht hinterher, die ![]() |
AW: Anonyme Methoden in Attributen
Zitat:
|
AW: Anonyme Methoden in Attributen
Zitat:
|
AW: Anonyme Methoden in Attributen
Zitat:
|
AW: Anonyme Methoden in Attributen
Zitat:
![]() ![]() Es gibt von Delphi ein paar Attribute, welche von Compiler oder VCL ausgewertet werden, wie z.B.
Delphi-Quellcode:
WeakAttribute, UnsafeAttribute, RefAttribute, DefaultAttribute, NoDefaultAttribute, StoredAttribute, ObservableMemberAttribute, ...
property int: Integer default 123;
[Default('abc')] property str: string; var [Weak] i: IInterface; |
AW: Anonyme Methoden in Attributen
Zitat:
Ich versuche es mal zu erklären. Grob gesagt: Es gibt eine abstrakte Basisklasse "TSearchProvider" mit einer Methode Search() und einer Liste von Methodenzeigern (TProcessSearchResult= procedure(SearchResult: TSearchResultObject) of object) die Funktionen auf die Daten bereitstellen die der SearchProvider findet. Nun gibt es ein "TSearchEngine" (Singleton) bei der TSearchProvider-Ableitungen (Instanzen dieser Ableitungen) registriert werden können. Im Programm selbst wird nur SearchEngine.Search('Suchbegriff') aufgerufen was daraufhin intern das Search('Suchbegriff') aller registrierten TSearchProvider-Objekte aufruft. TSearchEngine gruppiert die Suchergebnisse nach Providern. D.h. SearchEngine.Search gibt eine Liste mit Listen der Suchergebnisse der einzelnen Searchprovider zurück. Diese Listen (in der großen Liste) besitzen eine Referenz auf den Searchprovider der diese Liste "beigetragen" hat. Derjenige der nun SearchEngine.Search aufruft hat nun quasi sowas wie eine TGroupedResultList<TSearchProviderResultList<TSear chResultObject>> mit den Ergebnissen (wie gesagt: pro Searchprovider eine Liste). Der Aufrufer stellt nun die Ergebnisse in einem Grid dar und möchte dem Endbenutzer nun die Möglichkeit geben Operationen auf den Suchergebnissen auszuführen (per Popupmenu z.B.). Die SearchEngine hat natürlich keine Ahnung was für Daten sie da ausgespuckt hat. ALLERDINGS gibt es da die Liste der Operationen die die einzelnen SearchProvider bereitstellen (können). TSearchProviderResultList beinhaltet eine Referenz auf den Provider der wiederrum die Liste mit Methoden inkl. Caption für die Methoden bereitstellt. Nun kann der Aufrufer beim Popup des Popupmenus einfach dynamisch das Popupmenu mit den Aktionen füllen die im zum ausgewählten Suchergebnis zugehörigen Searchprovider enthalten sind. Nun kann es aber sein dass nicht für alle Suchergebnisse des selben Providers alle Operationen zur Verfügung stehen sollen (z.B. ein SearchProvider für Adressen mit der Operation "Bestellung schreiben", die natürlich nur bei Lieferanten und nicht bei Kunden angezeigt werden soll). Soweit so toll. Falls noch jemand am lesen ist: Nun zum eigentlichen Problem: Ich dachte damit derjenige der von TSearchProvider ableitet es relativ bequem hat erlaube ich einfach sowas:
Delphi-Quellcode:
Im constructor des abstrakten TSearchproviders würde ich dann per RTTI die Methoden durchlaufen und nach Methoden mit dieser Signatur + dem TSearchResultOperation-Attribut suchen und diese automatisch zu der Operationen-Liste hinzufügen mit dem im Attibut angegebenen Namen und anonymen Check-Procedure.
TAdresseSearchProvider = class(TSearchProvider)
public // Search() für Adressen überschreiben + anderer Kram ... // Operationen [TSearchResultOperation('Bestellung schreiben', function(AData: TSearchResultObject): Boolean begin Result := TAdressResult(AData).IstLieferant; end) ] procedure BestellungSchreiben(AData: TSearchResultObject); end; Somit muss derjenige der Ableitet sich um das hinzufügen zur Operationen-Liste nicht kümmern. Und beim Aufbau des PopupMenüs:
Delphi-Quellcode:
Da das mit den anonymen Methoden in den Attributen nicht geht habe ich es so gemacht dass TSearchProvider beim Durchsuchen der Methoden nachdem es eine Methode mit TSearchResultOperation-Attribut gefunden hat nach einer Methode sucht die genauso heißt + 'Check':
for i:= 0 to SelSearchResultObject.Provider.Operations.Count-1 do
begin // ACHTUNG: Starker Pseudocode: if SelSearchResultObject.Provider.Operations[i].CanUse(SelSearchResultObject) then // <-- anonyme Methode aus dem Attribut PopupMenu.AddItem(SelSearchResultObject.Provider.Operations[i].Name, SelSearchResultObject.Provider.Operations[i].Code); end;
Delphi-Quellcode:
Und diese wird dann in Operation.CanUse eingetragen.
oeprationCheckMethod := rttiType.GetMethod(operationMethod.Name + 'Check');
Der SearchProvider sieht dann so aus:
Delphi-Quellcode:
Und das ist nicht so schön.
TAdresseSearchProvider = class(TSearchProvider)
public // Search() für Adressen überschreiben + anderer Kram ... // Operationen [TSearchResultOperation('Bestellung schreiben'] procedure BestellungSchreiben(AData: TSearchResultObject); function BestellungSchreibenCheck(AData: TSearchResultObject): Boolean; end; Und Daniel: Ich hoffe du hast auch brav alles gelesen, du wolltest es ja wissen :mrgreen: :P (Ich hoffe man konnte es halbwegs verstehen :oops: ) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:58 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 by Thomas Breitkreuz