Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2018.10.28;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





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


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


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


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


15-1475011801
Юрий
2016-09-28 00:30
2018.10.28
С днем рождения ! 28 сентября 2016 среда





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский