Habe gerade damti gespielt (D2010) und kam zum Schluss, dass man Attribute in Delphi nur super-vorsichtig mit einer ganz langen Zange anfassen darf.
Ich würde sie nicht nutzen, schon gar nicht für etwas so kritisches wie einen ORM, da machsu dir lieber eine eigene DSL (mit ANTLR) oder denkst dir ein
XML-Format aus.
Hier meine Versuche, zwischendurch gab's wohl mehr sinnlose Fehler als keine und Error-Insight hatte, wie immer, Null Einsicht.
Wenn du also einen ORM schaffst, der Attribute unterstützt/benötigt, brauchen seine User eine sehr dicke Hornhaut.
Delphi-Quellcode:
program AttributesTest;
{$APPTYPE CONSOLE}
uses
SysUtils,
Rtti;
type
FieldAttribute =
class(TCustomAttribute)
private
fMappedName:
String;
public
property MappedName :
String read fMappedName
write fMappedName;
constructor Create;
overload;
constructor Create(mappedName :
String);
overload;
end;
constructor FieldAttribute.Create(mappedName:
String);
begin
fMappedName := mappedName;
end;
constructor FieldAttribute.Create();
begin
end;
type
SampleClass =
class
private
fMiep:
String;
fMööp:
String;
published
// [FieldAttribute(MappedName='A')] [DCC Fatal Error] AttributesTest.dpr(42): F2084 Internal Error: TI2180
[FieldAttribute('
A')]
// Workaround: 2. Ctor mit parameter :-/
property Miep :
String read fMiep
write fMiep;
//[&Field] geht nich! o_O
//[Field:] kompiliert o_O t, macht aber nix...
//[@Field] kompiliert o_O t, macht aber nix...
[FieldAttribute]
// WOrkaround: Voller Name mit Attribute-Suffix :-/
property Mööp :
String read fMööp
write fMööp;
end;
var
rttiContext : TRttiContext;
propInfo : TRttiProperty;
mappedFieldName :
String;
function GetMappedFieldName(propInfo : TRttiProperty) :
String;
var
attr : TCustomAttribute;
begin
for attr
in propInfo.GetAttributes()
do
if attr
is FieldAttribute
then
begin
if FieldAttribute(attr).MappedName <> '
'
then
exit (FieldAttribute(attr).MappedName);
exit (propInfo.
Name);
end;
exit ('
');
end;
begin
try
rttiContext := TRttiContext.Create();
try
for propInfo
in rttiContext.GetType(SampleClass).GetDeclaredProperties()
do
begin
mappedFieldName := GetMappedFieldName(propInfo);
if mappedFieldName <> '
'
then
Writeln(propInfo.
Name, '
-> ', mappedFieldName);
end;
finally
rttiContext.Free();
end;
except
on E:
Exception do
Writeln(E.ClassName, '
: ', E.
Message);
end;
end.