【问题标题】:Rtti accessing fields, properties and invoke method in record structuresRtti 访问记录结构中的字段、属性和调用方法
【发布时间】:2016-04-18 19:12:34
【问题描述】:

Rtti 访问记录结构中的字段、属性和调用方法。 我使用以下记录类型,来自site

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;

我研究了互联网上的所有示例,但徒劳无功。

【问题讨论】:

    标签: delphi rtti recordtype


    【解决方案1】:
    vType := vCtx.GetType(self);
    

    GetType 方法期望传递一个指向类型信息或类的指针,但你传递了一个实例。相反,您应该像这样传递类:

    vType := vCtx.GetType(ClassType);
    

    您不得将TRttiContext 传递给FreeAndNilTRttiContext 类型是一条记录。您无需在该类型上调用 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;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多