2016-04-18 17 views
1

レコード構造体のフィールド、プロパティ、および呼び出しメソッドにアクセスするRtti。 私は、次のレコードタイプを使用し、siteレコード構造体のフィールド、プロパティ、および呼び出しメソッドにアクセスするRtti

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;  

からである。しかし、私は、インターネット上の無駄だったすべての例を研究し

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; 

記録と、このコードは動作しません。

答えて

3
vType := vCtx.GetType(self); 

GetType方法は情報、またはクラスの型へのポインタを渡すことを期待していますが、インスタンスを渡します。代わりに、このようなクラスを渡す必要があります。

vType := vCtx.GetType(ClassType); 

あなたはFreeAndNilTRttiContextを渡してはいけません。 TRttiContextタイプはレコードです。そのタイプのCreateに電話する必要はありません。 Freeに電話する必要はありません。

さらに、メソッドを呼び出すコードは間違っています。

あなたの関数は次のようになります。

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; 

このコードは、少なくともメソッドを呼び出し、戻り値を取得しません。私はあなたがそこからそれを取るようにします。

関連する問題