2016-04-18 34 views
1

Rtti访问记录结构中的字段,属性和调用方法。 我用下面的记录类型,是从siteRtti访问记录结构中的字段,属性和调用方法

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); 

你不能传递一个TRttiContextFreeAndNilTRttiContext类型是一个记录。您不需要拨打该类型的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; 

该代码并至少调用方法和检索返回值。我会让你从那里拿走它。