Desde la versión 2010 de Delphi, se agregó a la Rtti los attributos, que corresponden con las anotaciones de otros lenguajes como Java o .Net.
Con esta nueva característica de la Rtti podemos añadir a clases, méodos o propiedades, atributos en tiempo de diseño y desarrollo que después podremos recuperar en tiempo de ejecución a través de la Rtti.
Para nosotros será útil para el desarrollo del framework que tenemos en marcha, ya que las utilizaremos para automatizar muchas cosas.
Como sabemos la Rtti lleva mucho tiempo con nosotros y como característica más importante (por lo menos para nuestro framework) es la de poder recuperar las propiedades de una clase, que se hace de forma sencilla
Si lanzamos la función sobre la clase TMyClass del articulo Serialización sencilla JSON (II) el resultado sería:
IntegerValue
DoubleValue
StringValue
Respecto a los atributos, descienden de la clase TCustomAttribute alojada en System.Rtti y para asociar el atributo a un tipo, método, campo o propiedad simplemente hay que ponerlo entre [] antes de su definición.
Para acceder en tiempo de ejecución a estos atributos, accederemos a la lista de atributos adjunta al tipo, método, campo o propiedad reflejados en la Rtti.
Si pasamos esta función sobre la calse TMyClass
Type: TMyclass (MyAttribute)
Property: IntegerValue (MyAttribute2)
Property: DoubleValue
Property: StringValue (MyAttribute3)
Además podemos crear propiedades a los atributos que después podremos recuperar, para ello los crearemos en la clase del atributo:
Si ponemos una pequeña modificación cuando recuperamos los atributos de las propiedades podemos recuperar estos valores
Si añadimos un valor a este atributo en la propiedad del ejemplo
Ahora el resultado de pasar la función sobre la clase
Type: TMyclass (MyAttribute)
Property: IntegerValue (MyAttribute2{Esto es SPARTA})
Property: DoubleValue
Property: StringValue (MyAttribute3)
Hemos visto como usar los atributos de la Rtti así de como recuperarlos de un tipo, método, campo o propiedad. Esta utilización de la Rtti será muy útil para nuestros propósitos.
Con esta nueva característica de la Rtti podemos añadir a clases, méodos o propiedades, atributos en tiempo de diseño y desarrollo que después podremos recuperar en tiempo de ejecución a través de la Rtti.
Para nosotros será útil para el desarrollo del framework que tenemos en marcha, ya que las utilizaremos para automatizar muchas cosas.
Como sabemos la Rtti lleva mucho tiempo con nosotros y como característica más importante (por lo menos para nuestro framework) es la de poder recuperar las propiedades de una clase, que se hace de forma sencilla
function GoGetProperties(const AClass: TClass): TStrings; var cxt: TRttiContext; t : TRttiType; p : TRttiProperty; begin Result := TStringList.Create; cxt := TRttiContext.Create; try t := cxt.GetType(AClass); for p in t.GetProperties do begin Result.Add(p.Name); end; finally cxt.Free; end; end;
Si lanzamos la función sobre la clase TMyClass del articulo Serialización sencilla JSON (II) el resultado sería:
IntegerValue
DoubleValue
StringValue
Respecto a los atributos, descienden de la clase TCustomAttribute alojada en System.Rtti y para asociar el atributo a un tipo, método, campo o propiedad simplemente hay que ponerlo entre [] antes de su definición.
type TMyAttribute = class(TCustomAttribute) end; TMyAttribute2 = class(TCustomAttribute) end; TMyAttribute3 = class(TCustomAttribute) end; [TMyAttribute] TMyClass = class ... [TMyAttribute2] property IntegerValue: Integer read FIntegerValue write FIntegerValue; property DoubleValue: Double read FDoubleValue write FDoubleValue; [TMyAttribute3] property StringValue: string read FStringValue write FStringValue; ... end; ...
Para acceder en tiempo de ejecución a estos atributos, accederemos a la lista de atributos adjunta al tipo, método, campo o propiedad reflejados en la Rtti.
function GoGetProperties2(const AClass: TClass): TStrings; var cxt: TRttiContext; t : TRttiType; p : TRttiProperty; Attr: TCustomAttribute; s: string; begin Result := TStringList.Create; cxt := TRttiContext.Create; try t := cxt.GetType(AClass); s := ''; for Attr in t.GetAttributes do begin s := ',' + Attr.ClassName; if Attr is TMyAttribute then begin // Este clase tiene asociado el atributo TMyAttribute end; end; if s'' then s := '('+s.Substring(2)+')'; Result.Add('Type: '+t.Name+' '+s); for p in t.GetProperties do begin s := ''; for Attr in p.GetAttributes do begin s := ',' + Attr.ClassName; if Attr is TMyAttribute2 then begin // Este propiedad tiene asociado el atributo TMyAttribute2 end; end; if s'' then s := '('+s.Substring(2)+')'; Result.Add(' Property: '+ p.Name+' '+s); end; finally cxt.Free; end; end;
Si pasamos esta función sobre la calse TMyClass
Type: TMyclass (MyAttribute)
Property: IntegerValue (MyAttribute2)
Property: DoubleValue
Property: StringValue (MyAttribute3)
Además podemos crear propiedades a los atributos que después podremos recuperar, para ello los crearemos en la clase del atributo:
... TMyAttribute2 = class(TCustomAttribute) private FValue: string; public property Value: string read FValue write FValue; constructor Create(const AValue: string = ''); end; ... constructor TMyAttribute2.Create(const AValue: string); begin FValue := AValue; end; ...
Si ponemos una pequeña modificación cuando recuperamos los atributos de las propiedades podemos recuperar estos valores
... if Attr is TMyAttribute2 then begin // Este propiedad tiene asociado el atributo TMyAttribute2 s := s + '{' + TMyAttribute2(Attr).Value + '}'; end; ...
Si añadimos un valor a este atributo en la propiedad del ejemplo
... [TMyAttribute2('Esto es SPARTA')] property IntegerValue: Integer read FIntegerValue write FIntegerValue; ...
Ahora el resultado de pasar la función sobre la clase
Type: TMyclass (MyAttribute)
Property: IntegerValue (MyAttribute2{Esto es SPARTA})
Property: DoubleValue
Property: StringValue (MyAttribute3)
Hemos visto como usar los atributos de la Rtti así de como recuperarlos de un tipo, método, campo o propiedad. Esta utilización de la Rtti será muy útil para nuestros propósitos.