2015-03-28 20 views
5

E 'possibile e come creare e collegare attributo personalizzato al campo in fase di esecuzione?Come creare e collegare attributo personalizzato al campo in fase di esecuzione in Delphi

uses 
    System.SysUtils, 
    System.Classes, 
    System.Rtti; 

type 
    MyAttribute = class(TCustomAttribute) 
    private 
    fCaption: string; 
    public 
    constructor Create(const aCaption: string); 
    property Caption: string read fCaption write fCaption; 
    end; 

    TFoo = class(TPersistent) 
    public 
    [MyAttribute('Title')] 
    Bar: string; 
    Other: string; 
    end; 

constructor MyAttribute.Create(const aCaption: string); 
begin 
    fCaption := aCaption; 
end; 

procedure CreateAttributes(Typ: TRttiType); 
var 
    Field: TRttiField; 
    MyAttr: MyAttribute; 
begin 
    for Field in Typ.GetFields do 
    begin 
     if Length(Field.GetAttributes) = 0 then 
     begin 
      MyAttr := MyAttribute.Create('Empty'); 
      // how to attach created attribute to Field ??? 
     end; 
    end; 
end; 

var 
    Context: TRttiContext; 
    Typ: TRttiType; 
    Field: TRttiField; 
    Attr: TCustomAttribute; 

begin 
    Context := TRttiContext.Create; 
    Typ := Context.GetType(TFoo); 

    CreateAttributes(Typ); 

    for Field in Typ.GetFields do 
    for Attr in Field.GetAttributes do 
     if Attr is MyAttribute then 
     writeln(Field.Name + ' ' + MyAttribute(Attr).Caption); 
    readln; 
    Context.Free; 
end. 

esecuzione sopra codice produce output:

Bar Title 

desidero iniettare MyAttribute con valore Empty ai campi che non hanno al momento dell'esecuzione produrre output seguente:

Bar Title 
Other Empty 

risposta

2

Il framework non fornisce alcun meccanismo per il collegamento di attributi in fase di runtime. Qualsiasi tentativo di farlo implicherebbe l'hacking del framework.

+0

Penso che potrebbe essere così. Ciò dimostra solo che gli attributi non sono molto più adatti per la serializzazione rispetto alla direttiva pubblicata. –

+0

@Dalija perché le opzioni di serializzazione variano in fase di esecuzione –

+0

Un motivo per questo è modificare la serializzazione delle classi al di fuori del tuo controllo, come in [serializzazione JSON senza garbage] (http://stackoverflow.com/questions/29276304/how-to-serialize -an-tlistt-to-json-without-garbage) –

0

Gli attributi sono magia in fase di compilazione. In fase di esecuzione non hai bisogno di cose del genere. Basta creare il proprio dizionario in cui il tipo e il membro (il membro può essere impostato come stringa) è la chiave e l'elenco degli attributi è il valore. E, quando è necessario controllare gli attributi, farlo in due modi: comuni e nel tuo dizionario.

+0

Grazie, ma questo non risolve il problema quando hai una classe al di fuori del tuo controllo (non puoi cambiarla in tempo di compilazione) e devi eseguire un'operazione basata sugli attributi (ancora al di là del tuo controllo) su di esso. Guarda [serializzazione JSON senza garbage] (http://stackoverflow.com/questions/29276304/how-to-serialize-an-tlistt-to-json-without-garbage) per ulteriori informazioni su ciò di cui sto parlando. –