2016-04-18 18 views
1

Rtti Zugriff auf Felder, Eigenschaften und Aufrufmethode in Datensatzstrukturen. ich die folgenden Datensatztypen verwenden, ist von siteRtti Zugriff auf Felder, Eigenschaften und Aufrufmethode in Datensatzstrukturen

type 
    Nullable<T> = record 
    public 
    FValue: T; 
    FHasValue: boolean; 
    procedure Clear; 
    function GetHasValue: boolean; 
    function GetValue: T; 
    constructor Create(AValue: T); 
     property HasValue: boolean read GetHasValue; 
    property Value: T read GetValue;  
    class operator Implicit(Value: Nullable<T>): T; 
    class operator Implicit(Value: T): Nullable<T>;  
    end;  
type  
    TIntEx = Nullable<integer>; 
    TSmallintEx = Nullable<smallint>;  

implementation 


constructor Nullable<T>.Create(AValue: T); 
begin 
    FValue := AValue; 
    FHasValue := false; 
end;  

function Nullable<T>.GetHasValue: boolean; 
begin 
    Result := FHasValue; 
end; 

function Nullable<T>.GetValue: T; 
begin 
    Result := FValue; 
end;  

class operator Nullable<T>.Implicit(Value: Nullable<T>): T; 
begin 
    Result := Value.Value; 
end; 

class operator Nullable<T>.Implicit(Value: T): Nullable<T>; 
begin 
    Result := Nullable<T>.Create(Value); 
end;  

Aber mit einem Rekord dieser Code funktioniert nicht

type 

    [TableName('Record')] 
    TMyrecord = class(TPersistent) 
    private 
    FRecno: TIntEx; 
    FName: TStringEx; 
    protected 
    public 
    constructor Create(); 
    destructor Destoy(); 
    function GetSqlInsert(): string; 
    [SqlFieldName('recno')] 
    property Recno: TIntEx read FRecno write FRecno; 
    [SqlFieldName('Name')] 
    property Name: TStringEx read FName write FName; 

    end; 

implementation 

{ TMyrecord } 

function TMyrecord.GetSqlInsert(): string; 
var 
    vCtx: TRttiContext; 
    vType: TRttiType; 
    vProp: TRttiProperty; 
    vAttr: TCustomAttribute; 
    vPropValue: TValue; 
    vRecord: TRttiRecordType; 
    M: TRttiMethod; 
    tmpStr: String; 
    val: TValue; 
begin 
    result := ''; 
    vCtx := TRttiContext.Create; 
    try 
    vType := vCtx.GetType(self); 
    for vProp in vType.GetProperties do 
     for vAttr in vProp.GetAttributes do 
     if vAttr is SqlFieldName then 
     begin 
      if (vProp.IsReadable) and (vProp.IsWritable) and 
      (vProp.PropertyType.TypeKind = tkRecord) then 
      begin 
      vRecord := vCtx.GetType(vProp.GetValue(self).TypeInfo).AsRecord; 
      M := vRecord.GetMethod('GetValue'); 
      if Assigned(M) then 
       vPropValue := (M.Invoke(vPropValue, [])); 
      tmpStr := val.ToString; 
      end; 

     end; 

    finally 
    freeandnil(vCtx); 
    end; 

end; 

ich alle Beispiele im Internet studiert, aber vergeblich.

Antwort

3
vType := vCtx.GetType(self); 

Die GetType Methode erwartet einen Zeiger übergeben werden Informationen zu geben, oder eine Klasse, aber sie passieren eine Instanz. Stattdessen sollten Sie die Klasse wie folgt passieren:

vType := vCtx.GetType(ClassType); 

Sie kein TRttiContext zu FreeAndNil passieren muss. Der TRttiContext Typ ist ein Datensatz. Sie müssen Create für diesen Typ nicht aufrufen. Sie müssen Free nicht anrufen.

Darüber hinaus ist Ihr Code zum Aufrufen der Methode einfach falsch.

Ihre Funktion könnte wie folgt aussehen:

function TMyrecord.GetSqlInsert(): string; 
var 
    vCtx: TRttiContext; 
    vType: TRttiType; 
    vProp: TRttiProperty; 
    vAttr: TCustomAttribute; 
    vRecord: TValue; 
    M: TRttiMethod; 
begin 
    vType := vCtx.GetType(ClassType); 
    for vProp in vType.GetProperties do 
    for vAttr in vProp.GetAttributes do 
     if vAttr is SqlFieldNameAttribute then 
     begin 
     if (vProp.IsReadable) and (vProp.IsWritable) and 
      (vProp.PropertyType.TypeKind = tkRecord) then 
     begin 
      vRecord := vProp.GetValue(self); 
      M := vProp.PropertyType.GetMethod('GetValue'); 
      if Assigned(M) then 
      begin 
      Result := M.Invoke(vRecord, []).ToString; 
      exit; 
      end; 
     end; 
     end; 
    Result := ''; 
end; 

Dieser Code dest nicht bei der Methode aufrufen und den Rückgabewert abzurufen. Ich lasse dich von dort nehmen.