Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2018.10.28;
Скачать: CL | DM;

Вниз

Array в RTTI (D7)   Найти похожие ветки 

 
mfender   (2013-02-02 21:07) [0]

Совсем не соображу как поступить. Уже и так и эдак повернул - не получается.

Беда в неосознании моём RTTI. В недостаточном сознании.


function ObjectToJSON(const AObj: TObject): TlkJSONObject;
var
 I: Integer;
 Cls: TClass;

 PropCnt: Integer;
 TypeData: PTypeData;
 PropList: PPropList;
 PropInfo: PPropInfo;

 V: Variant;
begin
 try
   Result := TlkJSONObject.Create(True);
   TypeData := GetTypeData(AObj.ClassInfo);
   if TypeData.PropCount > 0 then
   begin
     GetMem(PropList, SizeOf(PropInfo) * TypeData.PropCount);
     try
       TypInfo.GetPropInfos(AObj.ClassInfo, PropList);
       for I := 0 to Pred(TypeData.PropCount) do
       begin
         case PropList[I].PropType^.Kind of
           tkSet:
             Result.Add(PropList[I]^.Name, GetSetProp(AObj, PropList[I]));
           tkEnumeration, tkInteger:
             Result.Add(PropList[I]^.Name, GetOrdProp(AObj, PropList[I]));
           tkFloat:
             Result.Add(PropList[I]^.Name, GetFloatProp(AObj, PropList[I]));
           tkString, tkLString, tkWString:
             Result.Add(PropList[I]^.Name, GetStrProp(AObj, PropList[I]));
           tkClass:
             Result.Add(PropList[I]^.Name,
               ObjecttoJSON(GetObjectProp(AObj, PropList[I])) as TlkJSONBase);
           tkArray, tkDynArray:

{ Вот тут я очень не пойму что делать.  GetVariantProp() отвечает что Variant и Array - суть разные вещи. Меня это не удивляет, но я просто ума не приложу никак, что нужно с этим сделать? }

             Result.Add(PropList[I]^.Name,
               ArrayToJSON(GetVariantProp(AObj, PropList[I])) as TlkJSONBase);
           tkVariant:
             begin
               V := GetVariantProp(AObj, PropList[I]);
               case TVarData(V).VType of
                 varString:
                   Result.Add(PropList[I]^.Name, VarToStr(V));
               end;
             end;
           tkRecord:

{ А вот тут я вообще в заблуждении. Как пройти по всем "пунктам" record? }

             Continue;
         end;
       end;
     finally
       FreeMem(PropList, SizeOf(PropInfo) * TypeData.PropCount);
     end;
   end;
 except

 end;
end;

function ArrayToJSON(const Arr: array of const): TlkJSONList;
var
 I: Integer;
begin
 Result := TlkJSONList.Create;
 for I := Low(Arr) to High(Arr) do
 begin
   case Arr[I].VType of
     vtObject: Result.Add(ObjectToJSON(Arr[I].VObject));
   end;
 end;
end;


На ArrayToJSON() внимания не обращайте. До неё всё равно ничего пока не доходит. От столба написал.


 
Sapersky   (2013-02-02 22:57) [1]

В published properties не может быть массивов/рекордов.
Константы tkArray, tkDynArray, tkRecord - это для внутренней RTTI, которая нужна для обеспечения работы managed-типов (строк, дин. массивов и пр.).


 
mfender   (2013-02-03 00:02) [2]


> Sapersky   (02.02.13 22:57) [1]
>
> В published properties не может быть массивов/рекордов.
> Константы tkArray, tkDynArray, tkRecord - это для внутренней
> RTTI, которая нужна для обеспечения работы managed-типов
> (строк, дин. массивов и пр.).


Тем не менее...

 TRequestParamObject = class
 private
   FParamKey: string;
   FParamValue: Variant;
 published
   property ParamKey: string read FParamKey write FParamKey;
   property ParamValue: Variant read FParamValue write FParamValue;
 end;

 TReqParams = array of TRequestParamObject;

 TRequestParamsCollection = class
 private
   FItems: TReqParams;
   function GetItem(Idx: Integer): TRequestParamObject;
   procedure SetItem(Idx: Integer; AItem: TRequestParamObject);
   function GetJSON: TlkJSONList;
   procedure SetJSON(const Value: TlkJSONList);
 public
   procedure Add(Idx: Integer; Key: string; Value: Variant); overload;
   procedure Add(Key: string; Value: Variant); overload;
   property Item[idx: Integer]: TRequestParamObject read GetItem write SetItem;
   property JSON: TlkJSONList read GetJSON write SetJSON;
 published
   property Items: TReqParams read FItems write FItems;
 end;


И в этом случае, как ни крути, TRequestParamsCollection.Items - tkArray в вышеозначенном случае.
Иначе нахрена бы мне вообще спрашивать обо всём этом?


 
Sapersky   (2013-02-03 01:11) [3]

В D5 не компилируется. Я думал, все старые версии одинаковы в этом смысле.

Реально-то там есть RTTI, т.е. при трассировке в ветку tkArray, tkDynArray заходит? (в данном случае это tkDynArray)

D7 у меня нет, могу только погадать по XE3... но там extended RTTI и следовательно много нового по сравнению с D7. TypInfo.GetDynArrayProp, например, есть?
Ну или посмотри TypInfo.TTypeData, есть ли там секция tkDynArray.


 
mfender   (2013-02-03 08:07) [4]

Нет такого, в том-то вся беда.

http://i53.fastpic.ru/big/2013/0203/52/8397fc4b5682ce195842870b27e80552.png

Поэтому пока забил костыль путём собственного геттера в коллекции, который сериализует массив Items в JSON, потом уже добавляю его в JSON верхнего объекта. Не бог весть какое, но всё же решение. Просто очень уж хочется сделать достаточно универсальную функцию. )))


 
Sapersky   (2013-02-03 19:45) [5]

Здесь похожий вопрос:
http://stackoverflow.com/questions/4113480/rtti-how-get-values-of-dynamic-array-declared-as-class-property
Правда, в деталях решение проблемы не описывается. Вроде бы автор скопипастил нужный код из старших версий и у него заработало. Как-то так:

 const
   PROPSLOT_MASK    = $FF000000;
   PROPSLOT_FIELD   = $FF000000;

 function IsField(P: Pointer): Boolean; inline;
 begin
   Result := (DWord(P) and PROPSLOT_MASK) = PROPSLOT_FIELD;
 end;

 function GetField(Instance: TObject; P: Pointer): Pointer;
 begin
   Result := Pointer(DWord(Instance) + DWord(P) and not PROPSLOT_MASK);
 end;

 function ArrayToStr(Obj: TObject; Prop : PPropInfo): String;
 Type
   DByteArr = array of Byte;
 Var
   p : Pointer;
   n, Cnt : Integer;
 begin
   If not IsField(Prop.GetProc) then begin Result := ""; Exit; end;
   p := GetField(Obj, Prop.GetProc);
   // упрощённый вариант GetDynArrayProp, только для свойств без геттеров

   Cnt := Length(DByteArr(p^));
   Result := InttoStr(Cnt) + " ";
   // не знаю, можно ли в D7 можно получить тип элемента массива
   // Prop.PropType^.TypeData.elType - есть такое?
   // пока тип жёстко забит...
   for n := 0 to Cnt-1 do
     Result := Result + TReqParams(p^)[n].FParamKey + " ";
 end;


 
mfender   (2013-02-03 22:30) [6]

Спасибо, попробую из этого что-нибудь с утра выкроить. Может чего и получится.



Страницы: 1 вся ветка

Текущий архив: 2018.10.28;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.004 c
15-1475011801
Юрий
2016-09-28 00:30
2018.10.28
С днем рождения ! 28 сентября 2016 среда


15-1474296513
sniknik
2016-09-19 17:48
2018.10.28
Кто в курсе это глюк, фича, не понял что? (т.е. может меняться?)


6-1286523462
vv_fran
2010-10-08 11:37
2018.10.28
Как сохранить вложение из почты IdPOP3 ?


1-1359826540
azl
2013-02-02 21:35
2018.10.28
Фон компонента TJvDice


1-1359824833
mfender
2013-02-02 21:07
2018.10.28
Array в RTTI (D7)