代码之家  ›  专栏  ›  技术社区  ›  Blorgbeard

在运行时获取delphi记录中字段的偏移量

  •  6
  • Blorgbeard  · 技术社区  · 16 年前

    给定记录类型:

    TItem = record
       UPC : string[20];
       Price : Currency;
       Cost : Currency;
       ...
    end; 
    

    以及字段的名称 作为字符串

    例子:

    var
       pc : Integer;
       fieldName : string;
       value : Currency;
    begin
       pc := Integer(@item);                    // item is defined and filled elsewhere
       fieldName := Text1.Text;                 // user might type 'Cost' or 'Price' etc
       Inc(pc, GetItemFieldOffset(fieldName));  // how do I implement GetItemFieldOffset?
       value := PCurrency(pc)^;
       ..
    

    我用的是Delphi7。

    4 回复  |  直到 16 年前
        1
  •  8
  •   alex    16 年前

    你不能。delphi7不会为记录发出RTTI。还有其他选项(如前面的答案所示),但这些选项需要手动映射“字段名”->偏移量”。

        2
  •  4
  •   Lieven Keersmaekers    16 年前

    下面将为您的简化场景工作,但我怀疑是否有可能使这种事情的通用函数。

    登记

    function GetItemFieldOffset(const Value: string): Integer;
    var
      item: TItem;
    begin
      if Value = 'UPC' then Result := 0
      else if Value = 'Price' then Result := Integer(@item.Price) - Integer(@item)
      else if Value = 'Cost' then Result :=  Integer(@item.Cost) - Integer(@item)
      else raise Exception.CreateFmt('Unhandled condition (%0:s)', [Value]);
    end;
    
        3
  •  4
  •   Dan Bartlett    16 年前

    TItem = record
       UPC : string[20];
       Price : Currency;
       Cost : Currency;
    //...
    end;
        var
           rttiContext: TRttiContext;
           rttiType: TRttiType;
           fields: TArray<TRttiField>;
           item: TItem;
        begin
            rttiType := rttiContext.GetType(TypeInfo(TItem));
            caption := rttiType.Name + ' {';
            fields := rttiType.GetFields;
            for i := low(fields) to high(fields) do
            begin
              caption := caption +'{name='+fields[i].Name+',';
              caption := caption +'offset='+IntToStr(fields[i].Offset)+'}';
            end;
            caption := caption + '}';
    

    将产生'TItem{{name=UPC,offset=0}{name=Price,offset=24}{name=Cost,offset=32}'

    您还可以使用以下方法在特定实例中设置字段值(尽管您还应该验证类型):

    if fields[i].Name = 'Price' then
      fields[i].SetValue(@item, 10);
    
        4
  •  1
  •   Bharat    16 年前

    这就是你要找的吗

     type
       TItem = record
         UPC : string[20];
         Price : Currency;
         Cost : Currency;
         ...
       end; 
    
     var
       myRecord    : TItem ;
       myRecordPtr : ^TItem ;
    
     begin
       myRecord.price:= 100;
       myRecord.UPC := '111';
       myRecordPtr := @myRecord;
       if edit1.text = 'UPC' then   
         ShowMessage(myRecordptr.UPC);  // Displays '111'
       else if edit1.text = 'price' then   
         ShowMessage(myRecordptr.Price);  // Displays '100'
     end;
    
    推荐文章