![]() |
AW: Wozu sind Attribute gut ?
Nachdem ich mir Attribute nun auch etwas näher angesehen habe, stört mich eins doch irgendwie gewaltig: Vielleicht habe ich nicht lange genug im Wasser der AOP gebadet, aber spontan weiß ich nur einen Weg, an die Attribute zu kommen:
Mittels RTTI über
Delphi-Quellcode:
auf einem
GetAttributes(): TArray<TCustomAttribute>
Delphi-Quellcode:
. Nehmen wir an, ich habe eine ganz normale Property
TRttiObject
Delphi-Quellcode:
eines Objekts und möchte nun schauen, ob ein Attribut "Lebensmittel" für diese Property existiert bzw. ob dieses Attribut sagt "Wurst" oder "Käse". Jetzt muss ich über alle Properties meines Objekts iterieren, bis ich eine finde, welche den Namen 'Derp' hat. Nachdem ich die Property nun habe, kann ich wiederum alle Attribute durchsuchen, nach Namen suchen und weitermachen.
Derp
Das Durch-Iterieren stört mich nicht. Aber dass ich nicht Dinge tun kann wie
Delphi-Quellcode:
sondern doch hier eigentlich aufgrund der RTTI gezwungen bin, mit Zeichenfolgen zu arbeiten, oder? Soll bedeuten, ich muss in meinem Quelltext mindestens einen String mit dem Inhalt 'Derp' und 'Lebensmittel' ablegen. Ändere ich nun den Namen der Property und/oder des Attributs, habe ich ein Problem: Die Strings passen nicht mehr. Denn ich kenne keinen Weg, einer Methode eine "Property an sich" übergeben zu können. Attribute schon, das sind ja normale Klassen. Aber bei Properties scheitert es hier irgendwie...
meinObjekt.Derp.GetAttributes()
|
AW: Wozu sind Attribute gut ?
Zitat:
Mal ein Beispiel:
Delphi-Quellcode:
Und im Formular mit zwei Buttons und zwei Memos:
type
ColorElementAttribute = class(TCustomAttribute) private var FColor: TColor; procedure SetColor(const Value: TColor); public constructor Create(const AColor: TColor); property Color: TColor read FColor write SetColor; end; constructor ColorElementAttribute.Create(const AColor: TColor); begin FColor := AColor; end; procedure ColorElementAttribute.SetColor(const Value: TColor); begin FColor := Value; end;
Delphi-Quellcode:
Wenn ich den Namen des Attributes ändere, kompiliert das nicht mehr. Und in deinem Fall könnte das z.B. eine Enumeration sein, dann brauche ich auch da keinen String, das könnte dann auch beim Kompilieren geprüft werden.
TFormX = class(TForm)
Button1: TButton; Button2: TButton; [ColorElement(clRed)] Memo1: TMemo; [ColorElement(clBlue)] Memo2: TMemo; procedure Button1Click(Sender: TObject); end; procedure TFormX.Button1Click(Sender: TObject); var LCtx: TRttiContext; LField: TRttiField; LAttr: TCustomAttribute; begin for LField in LCtx.GetType(Self.ClassInfo).GetDeclaredFields do for LAttr in LField.GetAttributes do if LAttr is ColorElementAttribute then SetPropValue(LField.GetValue(Self).AsObject, 'Color', ColorElementAttribute(LAttr).Color); end; |
AW: Wozu sind Attribute gut ?
Das blöde ist nur, dass in
Delphi-Quellcode:
der Name der Property noch einmal redundant als String hinterlegt ist. Möchte ich den Namen der Property ändern, wäre ich so faul, das direkt mittels Refactoring-Funktionen zu erledigen. Das ändert direkt überall den Namen, wo die Property verwendet wird. Der String bleibt dabei natürlich unangetastet. Und fortan finde ich unter diesem Namen keine Property mehr.
SetPropValue(LField.GetValue(Self).AsObject, 'Color', ColorElementAttribute(LAttr).Color);
Auch die "alte RTTI" bietet nur das Finden über den Namen als String an. In anderen Sprachen habe ich auch nie wirklich etwas mit Reflection gemacht, ist das dort auch so? Mich bringt das um ehrlich zu sein ziemlich aus dem Konzept. Das mit der Enumeration ist ein interessanter Weg, das lasse ich mir mal durch den Kopf gehen :-) |
AW: Wozu sind Attribute gut ?
In C# macht man so etwas mit Expression trees, da sie refactoring-safe sind.
Eine naive Implementierung frei Schnauze:
Code:
Auf die Art kann man sich auch direkt PropertyInfos oder MethodInfos (vor allem den korrekten Overload) geben lassen. Sollte man aber möglichst so machen, dass es nicht unnötig oft passiert. Type-safe ist nett, aber schnell ist auch wichtig. ;-)
public static string GetName<TResult>(Expression<Func<TResult>> expression)
{ var me = expression.Body as MemeberExpressin; if(me != null) return me.Member.Name; var mce = expression.Body as MetodCallExpressin; if(mce != null) return mce.Method.Name; throw .... } var methodName = Xyz.GetName(() => "".Substring(0, 1)); // ergibt "Substring" |
AW: Wozu sind Attribute gut ?
Zitat:
|
AW: Wozu sind Attribute gut ?
Man könnte sich ja einen Class Helper basteln der die Typeinfo für das die Farbe darstellende Element zurückgibt :twisted:
|
AW: Wozu sind Attribute gut ?
Zitat:
Aber daran haben ja jetzt weniger die Attribute, sondern der Compiler an sich "Schuld". Vielleicht ändert sich das eines Tages ja mal. Die Class Helper und Dinge wie "42.toString()" sagen mir irgendwie, dass Hoffnung besteht :wink: |
AW: Wozu sind Attribute gut ?
Zitat:
Code:
ist nicht schneller als über die Expression.
var name = typeof(Foo).GetProperty("Bar").Name;
Zitat:
![]() Aber dazu müsste einiges am Compiler aufgebohrt werden - was aber nicht zuletzt einiges der arg hässlichen Implementierung der LiveBindings (jupp, die gehen komplett über magic string basierte RTTI) unnötig machen würde. |
AW: Wozu sind Attribute gut ?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:50 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