DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: webb123
今日帖子: 3
在线用户: 18
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 cenunus (cenunus) ★☆☆☆☆ -
普通会员
2018/10/23 20:26:59
标题:
RTTI到处是坑啊,也许是我太菜了 浏览:1391
加入我的收藏
楼主: 刚搞定了遍历枚举类型的取值,又跌进集合类型的坑里了,资料查了好多,试来试去都不行,希望大侠帮助~~
function GetSetAllName(obj: TObject; PName: string): TStringList;
var
  PropInfo: PPropInfo;
  PropType: PTypeInfo;
  TypeData: PTypeData;
  I: Integer;
begin
  Result:=TStringList.Create;
  PropInfo := GetPropInfo(obj, PName);
  PropType := PropInfo.PropType^;
  TypeData := GetTypeData(PropType);

  for I := TypeData.MinValue to TypeData.MaxValue do
  begin
    //Result.Add(GetEnumName(PropType, I));  注释掉的这行是遍历枚举类型的
    Result.Add(SetToString(PropInfo, I));
  end;

end;
集合类型不是有序类型,没法用遍历枚举类型的方法来做,没有思路啊。。。。感觉应该用数组来做,不知道怎么弄。。。
----------------------------------------------
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2018/10/23 20:59:15
1楼: for in set

也不知道你到底要做什么,想完全动态化就别用编译型语言。
----------------------------------------------
--
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2018/10/23 21:13:17
2楼: 点我学习新姿势
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 cenunus (cenunus) ★☆☆☆☆ -
普通会员
2018/10/23 22:11:54
3楼: 楼上的,感谢,进去看了不少代码,但是没找到获取所有集合类型的取值列表的,只找到取当前值的。。。。
----------------------------------------------
作者:
男 lsh341999 (虫子) ★☆☆☆☆ -
普通会员
2018/10/24 8:12:33
4楼: Function  TfxRttiPropertyItem.GetValueList:String;
Var
  i      :Integer;
  iList  :TStringList;
Begin
  iList  :=TStringList.Create;
  Try
    if Assigned(FPropInfo) then
    Begin
      //有扩展的属性
      if Assigned(FPropertyEditor) then
        Exit(TfxPropertyEditor(FPropertyEditor).GetValues);
      //无扩展的属性
      case FPropInfo.PropType^.Kind of
        tkInteger,tkChar, tkWChar,tkFloat,tkString, tkLString, tkWString, tkUString,tkSet:Exit('');
        tkEnumeration:Begin
          for I := FPropInfo.PropType^.TypeData.MinValue to FPropInfo.PropType^.TypeData.MaxValue do
          iList.Add(GetEnumName(FPropInfo.PropType^,I));
        End;
        tkClass:Begin
          if GetTypeData(FPropInfo.PropType^)^.ClassType.InheritsFrom(TComponent) then
          Begin
          for I := 0 to FRunObj.ComponentCount - 1 do
          if FRunObj.Components[i] is GetTypeData(FPropInfo.PropType^)^.ClassType then
          iList.Add(FRunObj.Components[i].Name);
          if iList.Count=0 then
          iList.Add('');
          End Else 
          Exit('');
        End;
        tkMethod:Begin
          Exit('');
        End;
      End;
    End Else Begin
      iList.Add('False');
      iList.Add('True'); 
    End;
      
    Exit(iList.Text);
  Finally
    FreeAndNil(iList);
  End;
End;
----------------------------------------------
就怕想不到,没有做不到的
作者:
男 cenunus (cenunus) ★☆☆☆☆ -
普通会员
2018/10/24 8:17:09
5楼: 楼上的,枚举类型的遍历我已经实现了,有问题的是集合类型,你的代码里也没有遍历集合类型啊~~谢谢~~
----------------------------------------------
作者:
男 lsh341999 (虫子) ★☆☆☆☆ -
普通会员
2018/10/24 10:19:29
6楼: 你是要获取集合的值还是集合枚举列表?
Function  TfxRttiPropertyItem.GetStrValue:String;
Var
  SetInt : TIntegerSet;
  i      :Integer;
  Ch     : Char;
Begin
  if Assigned(FPropInfo) then
  Begin
    case FPropInfo.PropType^.Kind of
      tkInteger:
        Exit(Inttostr(GetOrdProp(FParentObj,FPropInfo)));
      tkChar, tkWChar:Begin
        Ch := Chr(GetOrdProp(FParentObj,FPropInfo));
        {$IFDEF Delphi12}
          if CharInSet(Ch, [#33..#255]) then
        {$ELSE}
          if Ch in [#33..#255] then
        {$ENDIF}
          Result := Ch
          else
          FmtStr(Result, '#%d', [Ord(Ch)]);
      End;
      tkFloat:
        //Exit(Floattostr(GetFloatProp(FParentObj,FPropInfo)));
        Exit(Floattostr(StrToFloat(FormatFloat('0.000000'{只保留六位数},GetFloatProp(FParentObj,FPropInfo)))));
      tkString, tkLString, tkWString, tkUString:
        Exit(GetStrProp(FParentObj,FPropInfo));
      tkEnumeration:
        Exit(GetEnumName(FPropInfo.PropType^, GetOrdProp(FParentObj,FPropInfo)));
      tkSet:Begin
        Integer(SetInt) := GetOrdProp(FParentObj,FPropInfo);
        Result := '[';
        for i := GetTypeData(GetTypeData(FPropInfo.PropType^).CompType^)^.MinValue to GetTypeData(GetTypeData(FPropInfo.PropType^).CompType^)^.MaxValue do
          if i in SetInt then
          Begin
          if Length(Result) <> 1 then
          Result := Result + ',';
          Result := Result + GetEnumName(GetTypeData(FPropInfo.PropType^).CompType^, i);
          End;
        Result := Result + ']';
      End;
      tkClass:Begin
        if GetTypeData(FPropInfo.PropType^)^.ClassType.InheritsFrom(TComponent) then
        Begin
          if Assigned(TComponent(GetOrdProp(FParentObj,FPropInfo))) then
          Exit(TComponent(GetOrdProp(FParentObj,FPropInfo)).Name)
          Else
          Exit('');
        End Else if GetTypeData(FPropInfo.PropType^)^.ClassType.InheritsFrom(TPersistent) then
        Begin
          {$IFDEF NEXTGEN}
          Exit('TSymbolName'{'(' + String(FPropInfo.PropType^.Name) + ')'});//这里不知道怎么写,BYTE转STRING
          {$ELSE  NEXTGEN}
          Exit('(' + String(FPropInfo.PropType^.Name) + ')');
          {$ENDIF NEXTGEN}
        End;
      End;
      tkMethod:Begin
        Exit('');
      End;
    End;
  End Else Begin//集合子元素
    With TfxRttiPropertyList(Self.Collection).Parent do
      Integer(SetInt):=GetOrdProp(ParentObj,PropInfo);
    if Self.Index in SetInt then
      Exit('True');
    Exit('False');
  End;
End;
应该是这个了
----------------------------------------------
就怕想不到,没有做不到的
作者:
男 iamdream (银河恒久远,梦想无止境!) ★☆☆☆☆ -
大贡献会员
2018/10/24 10:20:04
6楼: Delphi有现成的源代码你不找,唉。你看一下TypInfo.pas中的SetToString函数就可以得到答案。
简单的测试可以用Rtti.pas(或System.Rtti.pas)中的TValue来做,比如在Form中可以这样写:
ShowMessage(TValue.From<TAnchors>(Self.Anchors).ToString);
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
男 cenunus (cenunus) ★☆☆☆☆ -
普通会员
2018/10/24 11:16:54
7楼: 感谢iamdream,感谢大家,问题已经搞定了
function GetSetAllName(obj: TObject; PName: string): TStringList;
var
  PropInfo: PPropInfo;
  PropType: PTypeInfo;
  I: Integer;
begin
  Result:=TStringList.Create;
  PropInfo := GetPropInfo(obj, PName);
  PropType := PropInfo.PropType^;

  for i := GetTypeData(GetTypeData(PropType).CompType^)^.MinValue to GetTypeData(GetTypeData(PropType).CompType^)^.MaxValue do
  begin
    Result.Add(GetEnumName(GetTypeData(PropType).CompType^, i));
  end;

end;
----------------------------------------------
作者:
男 pankangkang (aaaa) ★☆☆☆☆ -
普通会员
2018/10/24 11:28:35
8楼: 不写框架类的项目 感觉基本用不上RTTI
----------------------------------------------
-
作者:
男 feiyanm (feiyanm) ▲▲▲▲▲ -
普通会员
2018/10/24 13:36:59
9楼: 还好,楼主还没遇到Bool值的超级大坑,遇到再说吧。。。
----------------------------------------------
Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!我去WC吐一会儿去!
作者:
男 looper (keyo) ★☆☆☆☆ -
盒子活跃会员
2018/10/24 13:46:30
10楼: 一种通过泛型获取枚举类型所有枚举项名称的方法

function TForm1.GetEnumNames<T>: TArray<string>;
var
  RTX: TRttiContext;
  RT: TRttiType;
  ROT: TRttiOrdinalType;
  I: Integer;
  LNames: TArray<string>;
begin
  RT:= RTX.GetType(TypeInfo(T));
  if RT.IsOrdinal then
  begin
    ROT:= RT.AsOrdinal;
    SetLength(Result, ROT.MaxValue + 1);
    for I:= ROT.MinValue to ROT.MaxValue do
      Result[I]:= System.TypInfo.GetEnumName(TypeInfo(T), I);
  end;
end;

调用方法:
type
  TTest = (tt01, tt02, tt03, tt04, tt05);
var
  LNames: TArray<string>;
begin
  LNames:= GetEnumNames<TTest>; //这里可以传任意枚举类型
end.
----------------------------------------------
虽千万人吾往矣!
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2018/10/24 14:21:12
11楼: 集合虽然是无序的,但是集合里面是枚举,枚举是有序的,先取到集合的枚举,然后遍历集合。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 cnpack (CnPack) ★☆☆☆☆ -
普通会员
2018/10/24 14:25:14
11楼: CnPack组件包cnvcl\Source\Common\CnDebug.pas中有从Delphi5就支持的旧式RTTI下获取某set值的逗号分隔的字符串内容的方法。见CnDebugger.LogSet方法。

调用形式举例:LogSet(Anchors, SizeOf(Anchors), TypeInfo(TAnchorKind));

https://github.com/cnpack/cnvcl
----------------------------------------------
欢迎使用CnPack IDE Wizards
http://www.cnpack.org/
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行679.6875毫秒 RSS