AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

Ein Thema von freejay · begonnen am 17. Okt 2017 · letzter Beitrag vom 18. Okt 2017
Antwort Antwort
Seite 1 von 2  1 2   
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#1

Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 13:47
Hallo zusammen,

wenn ich ein String-Property
Code:
MySet
habe und ein zugehöriges Feld
Code:
FMySet
vom Typ
Code:
TMySet = (Hund,Katze,Maus)
dann muss ich manuell einen GETter und einen SETter dafür schreiben. Und sobald neue Ausprägunge dazu kommen (z.B. Giraffe, Känguru), dann muss ich jedesmal auch die Get- und Set-Routinen erweitern.

Und das ist eine ziemlich lästige aber/und primitive Aufgabe, da es dabei eigentlich immer nur um ein

Code:
else if Value = "Katze" then
  FMySet := Katze
else...
geht.

Müsste es nicht möglich sein, mit Hilfe der RTTI universelle Getter und Setter für Aufzählungstypen zu entwickeln, die die verfügbaren Werte als String ermitteln können und daher in einer Schleife für beliebige Aufzählungen funktionieren würden?

Ich habe mich bislang nicht viel mit der RTTI beschäftigt und hätte - bevor ich mich da voll reinhänge - gerne von Erfahreneren eine Einschätzung dazu.

Danke im Voraus & sonnige Grüße aus Nürnberg

Freejay
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#2

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:02
IMO solltest du lieber das eigentliche Problem lösen, nämlich, dass du für eine begrenzte Menge an Möglichkeiten (enum) eine Eigenschaft vom Typ string hast und nicht vom Typ deines enums.

Trotzdem noch etwas zu deiner Frage - klar, kann man irgendwie mit RTTI drauf schießen, ist aber imo unnötig. Delphi bietet die Möglichkeit, konstane statische Arrays über einen Enum zu definieren.

Delphi-Quellcode:
uses
  StrUtils,
  SysUtils;

type
  TPet = (Hund,Katze,Maus);

const
  CPetNames: array[TPet] of string = ('Hund','Katze','Maus');

function TryGetEnumValue(const s: string; out value: TPet): Boolean;
var
  i: Integer;
begin
  i := IndexText(s, CPetNames);
  Result := i > -1;
  if Result then
    value := TPet(i);
end;
Das ganze kann man natürlich auch generisch und über RTTI lösen, aber dann muss man sich was überlegen, ob aus dem enum Wert die entsprechenden Namen zu ermitteln, sollten die mal nicht 1-zu-1 zusammen passen oder lokalisierbar sein.

Aber nochmal, ich würd lieber mit dem enum Typ arbeiten und erst dort, wo man einen string benötigt (z.B. in der UI) umwandeln. Ansonsten hat man ein "stringly typed" System.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (17. Okt 2017 um 14:04 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#3

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:08
Meinst Du sowas?
Delphi-Quellcode:
uses
  Classes,
  TypInfo;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen und gibt }
{ diese in der Stringliste zurück.                                             }
procedure TRTTI.GetEnumTypeInfo(AClass: TObject);
begin
  GetEnumTypeInfo(PTypeInfo(AClass));
end;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen und gibt }
{ diese in der Stringliste zurück.                                             }
procedure TRTTI.GetEnumTypeInfo(ATypeInfo: PTypeInfo);
var
  OrdTypeData : PTypeData;
  TypeNameStr : String;
  TypeKindStr : String;
  MinVal : Integer;
  MaxVal : Integer;
  i : integer;
begin
  // TTypeData-Pointer holen
  OrdTypeData := GetTypeData(ATypeInfo);
  // Typnamen holen
  TypeNameStr := ATypeInfo.Name;
  // Typart als String holen
  TypeKindStr := GetEnumName(TypeInfo(TTypeKind), Integer(ATypeInfo^.Kind));
  // Niedrigsten und höchstmöglichen Wert holen
  MinVal := OrdTypeData^.MinValue;
  MaxVal := OrdTypeData^.MaxValue;
  // Informationen in Stringliste übernehmen
  FHtml.Add('<ul class="dot">');
  FHtml.Add('<li><em class="Name">Type Name: ' + TypeNameStr + '</em></li>');
  FHtml.Add('<li><em class="Kind">Type Kind: ' + TypeKindStr + '</em></li>');
  // Der gibt zuweilen seltsame Abstürze, das Programm ist einfach weg.
  If ATypeInfo^.Kind in [tkInteger, tkChar, tkEnumeration, tkFloat, tkInt64] Then Begin
    FHTML.Add('<li style="list-style: none">');
    FHtml.Add('<ul class="dot">');
    FHtml.Add('<li><em class="MinMax">Min Val: ' + IntToStr(MinVal) + '</em></li>');
    FHtml.Add('<li><em class="MinMax">Max Val: ' + IntToStr(MaxVal) + '</em></li>');
    // Mögliche Werte und Namen von Aufzählungstypen holen
    // WordBool geht als Aufzählungstyp von -2147483648 bis 2147483647.
    // Das ist etwas zuviel, um alle Werte aufzulisten.
    if (ATypeInfo^.Kind = tkEnumeration) And (UpperCase(TypeNameStr) <> 'WORDBOOL') then Begin
      FHTML.Add('<li style="list-style: none">');
      FHtml.Add('<table class="small">');
      Try
        // Eigentlich sollte man meinen, das MinVal kleiner als MaxVal ist,
        If MinVal < MaxVal Then Begin
          for i := MinVal to MaxVal do Begin
            FHtml.Add('<tr><td class="left" width="10%"><ul class="dot"><li><em class="Value">Value: ' + IntToStr(i) + '</em></li></ul></td>'
                        + '<td class="left" width="30%"><ul class="dot"><li><em class="Value">Name: ' + GetEnumName(ATypeInfo, i) + '</em></li></ul></td></tr>');
          End;
        End Else Begin // ist es aber bei TOleEnum nicht
          for i := MinVal Downto MaxVal do Begin
            FHtml.Add('<tr><td class="left" width="10%"><ul class="dot"><li><em class="Value">Value: ' + IntToStr(i) + '</em></li></ul></td>'
                        + '<td class="left" width="30%"><ul class="dot"><li><em class="Value">Name: ' + GetEnumName(ATypeInfo, i) + '</em></li></ul></td></tr>');
          End;
        End;
      Except
        FHtml.Add('<tr><td>Values nicht zu ermitteln.</td></tr>');
      End;
      FHtml.Add('</table>');
      FHtml.Add('</li>');
    End;
    FHtml.Add('</ul>');
    FHtml.Add('</li>');
  End Else Begin
  End;
  FHtml.Add('</ul>');
end;
Ist ein Fragment aus einer Klasse, mit der ich mir die Dokumantation eines Programmes, einer Klasse ... über RTTI generiere und mit Delphi 7 geschrieben.
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:19
IMO solltest du lieber das eigentliche Problem lösen, nämlich, dass du für eine begrenzte Menge an Möglichkeiten (enum) eine Eigenschaft vom Typ string hast und nicht vom Typ deines enums.

Trotzdem noch etwas zu deiner Frage - klar, kann man irgendwie mit RTTI drauf schießen, ist aber imo unnötig. Delphi bietet die Möglichkeit, konstane statische Arrays über einen Enum zu definieren.

Delphi-Quellcode:
uses
  StrUtils,
  SysUtils;

type
  TPet = (Hund,Katze,Maus);

const
  CPetNames: array[TPet] of string = ('Hund','Katze','Maus');

function TryGetEnumValue(const s: string; out value: TPet): Boolean;
var
  i: Integer;
begin
  i := IndexText(s, CPetNames);
  Result := i > -1;
  if Result then
    value := TPet(i);
end;
Das ganze kann man natürlich auch generisch und über RTTI lösen, aber dann muss man sich was überlegen, ob aus dem enum Wert die entsprechenden Namen zu ermitteln, sollten die mal nicht 1-zu-1 zusammen passen oder lokalisierbar sein.

Aber nochmal, ich würd lieber mit dem enum Typ arbeiten und erst dort, wo man einen string benötigt (z.B. in der UI) umwandeln. Ansonsten hat man ein "stringly typed" System.
Ich benutze ja den Enum Typ. Nur in der Kommunikation nach aussen (eingelesene bzw. rausgeschriebene Daten) brauche ich dann einen String.

Dein Vorschlag würde die Anzahl Stellen, an denen etwas gemacht werden muss (wenn neue Werte hinzukommen) immerhin schon mal von 3 auf 2 reduzieren und den pro-Wert-Aufwand zusätzlich verringern.

Was mich an dieser (und erst recht an meiner) Lösung trotzdem noch stört, ist, dass ich quasi die gleichen Texte zweimal (bei mir: drei mal) im Code aufführen und ergänzen muss (Hund und 'Hund')...
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:23
Meinst Du sowas?
... Ist ein Fragment aus einer Klasse, mit der ich mir die Dokumantation eines Programmes, einer Klasse ... über RTTI generiere und mit Delphi 7 geschrieben.
Danke: Das muss ich mir erstmal ausführlicher ansehen... Im Moment sehe ich nur überall HTML-Tags...
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#6

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:32
Ungetestet EntHTMLisiert und GeShowMessaged
Delphi-Quellcode:
uses
  Classes,
  TypInfo;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen. }
procedure TRTTI.GetEnumTypeInfo(AClass: TObject);
begin
  GetEnumTypeInfo(PTypeInfo(AClass));
end;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen. }
procedure TRTTI.GetEnumTypeInfo(ATypeInfo: PTypeInfo);
var
  OrdTypeData : PTypeData;
  TypeNameStr : String;
  TypeKindStr : String;
  MinVal : Integer;
  MaxVal : Integer;
  i : integer;
begin
  // TTypeData-Pointer holen
  OrdTypeData := GetTypeData(ATypeInfo);
  // Typnamen holen
  TypeNameStr := ATypeInfo.Name;
  // Typart als String holen
  TypeKindStr := GetEnumName(TypeInfo(TTypeKind), Integer(ATypeInfo^.Kind));
  // Niedrigsten und höchstmöglichen Wert holen
  MinVal := OrdTypeData^.MinValue; // Kleinster Wert
  MaxVal := OrdTypeData^.MaxValue; // Höchster Wert
  // Type Name = TypeNameStr
  // Type Kind = TypeKindStr
  If ATypeInfo^.Kind in [tkInteger, tkChar, tkEnumeration, tkFloat, tkInt64] Then Begin
    if (ATypeInfo^.Kind = tkEnumeration) And (UpperCase(TypeNameStr) <> 'WORDBOOL') then Begin
      Try
        // Eigentlich sollte man meinen, das MinVal kleiner als MaxVal ist,
        If MinVal < MaxVal Then Begin
          for i := MinVal to MaxVal do Begin
            // Verbale Beschreibung = GetEnumName(ATypeInfo, i) // Also z. B. Hund
            ShowMessage(GetEnumName(ATypeInfo, i));
          End;
        End Else Begin // ist es aber bei TOleEnum nicht
          for i := MinVal Downto MaxVal do Begin
            // Verbale Beschreibung = GetEnumName(ATypeInfo, i) // Also z. B. Hund
            ShowMessage(GetEnumName(ATypeInfo, i));
          End;
        End;
      Except
        // Fehlerbehandlung
      End;
    End;
  End;
end;
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:36
Meinst Du sowas?
... Ist ein Fragment aus einer Klasse, mit der ich mir die Dokumantation eines Programmes, einer Klasse ... über RTTI generiere und mit Delphi 7 geschrieben.
Danke: Das muss ich mir erstmal ausführlicher ansehen... Im Moment sehe ich nur überall HTML-Tags...
Ja, das könnte mir helfen.

Werde ich "die Tage" mal ausprobieren.

Vielen Dank!
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:38
Ungetestet EntHTMLisiert und GeShowMessaged
Delphi-Quellcode:
uses
  Classes,
  TypInfo;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen. }
procedure TRTTI.GetEnumTypeInfo(AClass: TObject);
begin
  GetEnumTypeInfo(PTypeInfo(AClass));
end;

{ Die Prozedur liefert Informationen zum übergebenen Aufzählungstypen. }
procedure TRTTI.GetEnumTypeInfo(ATypeInfo: PTypeInfo);
var
  OrdTypeData : PTypeData;
  TypeNameStr : String;
  TypeKindStr : String;
  MinVal : Integer;
  MaxVal : Integer;
  i : integer;
begin
  // TTypeData-Pointer holen
  OrdTypeData := GetTypeData(ATypeInfo);
  // Typnamen holen
  TypeNameStr := ATypeInfo.Name;
  // Typart als String holen
  TypeKindStr := GetEnumName(TypeInfo(TTypeKind), Integer(ATypeInfo^.Kind));
  // Niedrigsten und höchstmöglichen Wert holen
  MinVal := OrdTypeData^.MinValue; // Kleinster Wert
  MaxVal := OrdTypeData^.MaxValue; // Höchster Wert
  // Type Name = TypeNameStr
  // Type Kind = TypeKindStr
  If ATypeInfo^.Kind in [tkInteger, tkChar, tkEnumeration, tkFloat, tkInt64] Then Begin
    if (ATypeInfo^.Kind = tkEnumeration) And (UpperCase(TypeNameStr) <> 'WORDBOOL') then Begin
      Try
        // Eigentlich sollte man meinen, das MinVal kleiner als MaxVal ist,
        If MinVal < MaxVal Then Begin
          for i := MinVal to MaxVal do Begin
            // Verbale Beschreibung = GetEnumName(ATypeInfo, i) // Also z. B. Hund
            ShowMessage(GetEnumName(ATypeInfo, i));
          End;
        End Else Begin // ist es aber bei TOleEnum nicht
          for i := MinVal Downto MaxVal do Begin
            // Verbale Beschreibung = GetEnumName(ATypeInfo, i) // Also z. B. Hund
            ShowMessage(GetEnumName(ATypeInfo, i));
          End;
        End;
      Except
        // Fehlerbehandlung
      End;
    End;
  End;
end;
Oh danke! Das wär doch nicht nötig gewesen...
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#9

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:42
Wieso nicht, das Original ist ja nun mal auch unübersichtlich

Wesentlich wäre: Liefert die die Routine ansatzweise im ShowMessage solche Werte, wie Du erwartest?

Ansonsten ist's ja vergeblich

Oh, da fand ich noch dashier: http://www.swissdelphicenter.ch/de/showcode.php?id=389
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Automatischer Setter/Getter für Aufzählungs-Variablen via RTTI?

  Alt 17. Okt 2017, 14:58
Das kann ich frühestens morgen testen.
Gebe dann nochmal Rückmeldung.
Danke nochmal!
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:50 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