Thread View: pl.comp.lang.delphi
14 messages
14 total messages
Started by immo
Thu, 24 Jan 2019 13:59
RTTI SetValue i TValue.FromVariant
Author: immo
Date: Thu, 24 Jan 2019 13:59
Date: Thu, 24 Jan 2019 13:59
53 lines
1818 bytes
1818 bytes
Witam, Nigdy "ręcznie" nie bawiłem się RTTI, zawsze używałem armatę na muchę. Ale tym razem chciałem coś banalnego zrobić i poległem. Mianowicie, chciałem odczytać i zapisać dowolne property komponentu, a później ustawić to wcześniej zapisane. I o ile pobranie wartości property jako Variant i zapisanie gdziekolwiek nie robi problemu. Tzn wszystko działa i zapisuje się poprawnie. To tyle już ustawienie property rodzi problemy. Krótki przykład: var ctx : TRttiContext; rttiType : TRttiType; rttiProp : TRttiProperty; value: variant; rttiValue: TValue; Begin Value := GetDBValueAsVariant; rttiValue := TValue.FromVariant(Value); ShowMessage(rttiValue.ToString); //tutaj pokazuje poprawne wartości ctx := TRttiContext.Create; rttitype := ctx.GetType(jakiś np. ComboBox.ClassType); rttiprop := rttitype.GetProperty('ItemIndex'); rttiProp.SetValue(jakiś np. ComboBox,rttiValue); end; i problem jest taki, że jak rttiValue jest brane z Varianta, to przy podstawianiu dostaje w ostatniej linii invalid type cast. Jeśli Value zmienie na integer a TValue.FromVarian na TValue.From(value) to przy podstawieniu nie ma błędu i działa ok. Jednak takie rozwiązanie jest do bani, bo ja chcę żeby to działało ze wszystkimi property (integer, string, datetime, color itp. itd.). Tak sobie szukam po necie i raczej nie znalazłem rozwiązania, bo wszystkie albo są proste tak jak powyżej, albo dla kolekcji czy bardziej złożonych propertiesów. Pytanie - czy ktoś mógłby nakierować mnie co jest nie tak? pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 00:51
Date: Fri, 25 Jan 2019 00:51
32 lines
1113 bytes
1113 bytes
W dniu piątek, 25 stycznia 2019 08:33:53 UTC+1 użytkownik Roman Tyczka napisał: > On Thu, 24 Jan 2019 13:59:34 -0800 (PST), immo wrote: > > > > i problem jest taki, że jak rttiValue jest brane z Varianta, to przy podstawianiu dostaje w ostatniej linii invalid type cast. > > > > Jeśli Value zmienie na integer a TValue.FromVarian na TValue.From(value) to przy podstawieniu nie ma błędu i działa ok. > > > > Jednak takie rozwiązanie jest do bani, bo ja chcę żeby to działało ze wszystkimi property (integer, string, datetime, color itp. itd.). > > > > > > Tak sobie szukam po necie i raczej nie znalazłem rozwiązania, bo wszystkie albo są proste tak jak powyżej, albo dla kolekcji czy bardziej złożonych propertiesów. > > > > > > Pytanie - czy ktoś mógłby nakierować mnie co jest nie tak? > > Jakie Delphi? Ten problem konkretnie w Delphi XE2, ale nakierowałeś mnie - muszę to sprawdzić w najnowszym :) pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 01:32
Date: Fri, 25 Jan 2019 01:32
33 lines
1186 bytes
1186 bytes
W dniu piątek, 25 stycznia 2019 09:51:28 UTC+1 użytkownik immo napisał: > Ten problem konkretnie w Delphi XE2, ale nakierowałeś mnie - muszę to sprawdzić w najnowszym :) I sprawdzone - nie ma znaczenia :) W RIO tez jest tak samo. Co ciekawe w TValue.Cast typ w PTypeInfo jest poprawny - czyli tkInteger. --- trochę sobie pobiegałem po kodzie źródłowym i w System.rtti jest TValue.TryCast gdzie AtypeInfo jest tkInteger (czyli to co ma być) a System.TypeInfo(TValue) jest tkString bo faktycznie jako string jest przechowywany Variant. I teraz całą prockę przechodzi i na koniec mamy linię Result := Conversions[FData.FTypeInfo^.Kind, ATypeInfo^.Kind](Self, ATypeInfo, AResult); Gdzie Conversions to const Conversions: array[TTypeKind,TTypeKind] of TConvertFunc = ( // [source, target] i dla tkInteger jako target i tkString jako source mamy = ConvFail :) Trochę to dziwne, bo nie widzę problemu konwersji stringa do integera :P No ale problem rozwiązany - w sensie - Delphi tak ma, nie wnikając w zasadność. pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 01:34
Date: Fri, 25 Jan 2019 01:34
43 lines
1554 bytes
1554 bytes
W dniu piątek, 25 stycznia 2019 10:29:34 UTC+1 użytkownik Roman Tyczka napisał: > On Fri, 25 Jan 2019 00:51:26 -0800 (PST), immo wrote: > > >>> i problem jest taki, że jak rttiValue jest brane z Varianta, to przy podstawianiu dostaje w ostatniej linii invalid type cast. > >>> > >>> Jeśli Value zmienie na integer a TValue.FromVarian na TValue.From(value) to przy podstawieniu nie ma błędu i działa ok. > >>> > >>> Jednak takie rozwiązanie jest do bani, bo ja chcę żeby to działało ze wszystkimi property (integer, string, datetime, color itp. itd.). > >>> > >>> > >>> Tak sobie szukam po necie i raczej nie znalazłem rozwiązania, bo wszystkie albo są proste tak jak powyżej, albo dla kolekcji czy bardziej złożonych propertiesów. > >>> > >>> > >>> Pytanie - czy ktoś mógłby nakierować mnie co jest nie tak? > >> > >> Jakie Delphi? > > > > Ten problem konkretnie w Delphi XE2, ale nakierowałeś mnie - muszę to sprawdzić w najnowszym :) > > Tak myślałem, że jakiś antyk jest na tapecie, a antyki miały spore problemy > z RTTI (i generykami) ;-) > > W Tokyo (i kilku wersjach wstecz) to działa, bo niby czemu nie? > > -- > pozdrawiam > Roman Tyczka Jesteś pewien że działa? Właśnie sprawdziłem w RIO i jego źródłach i nie ma prawa działać :P pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 01:50
Date: Fri, 25 Jan 2019 01:50
25 lines
682 bytes
682 bytes
W dniu piątek, 25 stycznia 2019 10:32:31 UTC+1 użytkownik immo napisał: I żeby nie było, że nie ma rozwiązania, to zrobiłem sobie coś takiego (brzydkie ale działa) Że przed podstawieniem TValue do propertiesa sprawdzam jakiego jest typu i robię jawnie konwersję. czyli: case rttiProp.PropertyType.TypeKind of tkInteger : Value := StrToInt tkFloat: Value := StrToFloat tkString : Value := po prostu string :) end; rttiValue := TValue.FromVariant(Value); rttiProp.SetValue(jakiś komponent, rttiValue) gdzie Value: Variant rttiProp: TRttiProperty; rttiValue: TValue; pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 04:34
Date: Fri, 25 Jan 2019 04:34
22 lines
846 bytes
846 bytes
W dniu piątek, 25 stycznia 2019 12:04:54 UTC+1 użytkownik Roman Tyczka napisał: > On Fri, 25 Jan 2019 11:49:31 +0100, Roman Tyczka wrote: > > >> Taki kod przestawia mi itemindex z 0 na 1. Bez błędów i problemów. > > > > U Ciebie pewnie problemem jest metoda GetDBValueAsVariant, która robi > > Varianta integerowego jako stringowego. I stąd ambaras. > > Gdybyś w metodzie GetDBValueAsVariant, gdzie wiesz jakiego typu jest > kolumna w taneli, uży do zwracania varianta czegoś takiego: > > result := TValue.From<ColumnType>(DBValue).AsVariant > > to problemy by zniknęły imho. No chyba nie :) W tabeli jest string, a jak pokazałem powyżej w kodzie w System.Rtti przy Convert dla tkString do tkInteger jest ConvFail :) pozdrawiam, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: immo
Date: Fri, 25 Jan 2019 06:17
Date: Fri, 25 Jan 2019 06:17
43 lines
1731 bytes
1731 bytes
W dniu piątek, 25 stycznia 2019 14:16:44 UTC+1 użytkownik Roman Tyczka napisał: > On Fri, 25 Jan 2019 04:34:47 -0800 (PST), immo wrote: > Sprawdziłem ten kod, działa: > > procedure test; > var > ctx : TRttiContext; > rttiType : TRttiType; > rttiProp : TRttiProperty; > value: variant; > rttiValue: TValue; > v: Variant; > Begin > v := '5'; //czyli variant "stringowy" > Value := TValue.From<Integer>(v).AsVariant; > rttiValue := TValue.FromVariant(Value); > ctx := TRttiContext.Create; > rttitype := ctx.GetType(frmMain.cbbServerAddress.ClassInfo); > rttiprop := rttitype.GetProperty('ItemIndex'); > rttiProp.SetValue(frmMain.cbbServerAddress, rttiValue); > end; No tak zadziała to jawnie konwertujesz stringa do integera :) Podobne rozwiązanie podałem powyżej. Natomiast chodzi o to, że jeśli TValue w środku ma varianta stringowego to nie potrafi go skonwertować do integera. I tyle. Zastanawiam się tylko, czy jest jakiś powód takiego działania, czy po prostu zaniedbanie, błąd, czy może zostawione to jest na wieczne "później". Bo mając informacje o tym jakiego rodzaju jest property, mając informacje jakiego rodzaju jest variant w TValue nie problem przekonwertować stringa do integera... Albo przerobić SetValue, zeby nie wymagał TValue tylko Varianta... Wiem że varianty są kapryśne w niektórych zastosowaniach - może to jest problemem dlaczego to jest tak a nie inaczej? Zresztą - nieważne - to już tylko dywagacje na ten temat :) pozdrawiam i miłego weekendu, Przemek O.
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 08:33
Date: Fri, 25 Jan 2019 08:33
19 lines
752 bytes
752 bytes
On Thu, 24 Jan 2019 13:59:34 -0800 (PST), immo wrote: > i problem jest taki, że jak rttiValue jest brane z Varianta, to przy podstawianiu dostaje w ostatniej linii invalid type cast. > > Jeśli Value zmienie na integer a TValue.FromVarian na TValue.From(value) to przy podstawieniu nie ma błędu i działa ok. > > Jednak takie rozwiązanie jest do bani, bo ja chcę żeby to działało ze wszystkimi property (integer, string, datetime, color itp. itd.). > > > Tak sobie szukam po necie i raczej nie znalazłem rozwiązania, bo wszystkie albo są proste tak jak powyżej, albo dla kolekcji czy bardziej złożonych propertiesów. > > > Pytanie - czy ktoś mógłby nakierować mnie co jest nie tak? Jakie Delphi? -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 10:29
Date: Fri, 25 Jan 2019 10:29
25 lines
1059 bytes
1059 bytes
On Fri, 25 Jan 2019 00:51:26 -0800 (PST), immo wrote: >>> i problem jest taki, że jak rttiValue jest brane z Varianta, to przy podstawianiu dostaje w ostatniej linii invalid type cast. >>> >>> Jeśli Value zmienie na integer a TValue.FromVarian na TValue.From(value) to przy podstawieniu nie ma błędu i działa ok. >>> >>> Jednak takie rozwiązanie jest do bani, bo ja chcę żeby to działało ze wszystkimi property (integer, string, datetime, color itp. itd.). >>> >>> >>> Tak sobie szukam po necie i raczej nie znalazłem rozwiązania, bo wszystkie albo są proste tak jak powyżej, albo dla kolekcji czy bardziej złożonych propertiesów. >>> >>> >>> Pytanie - czy ktoś mógłby nakierować mnie co jest nie tak? >> >> Jakie Delphi? > > Ten problem konkretnie w Delphi XE2, ale nakierowałeś mnie - muszę to sprawdzić w najnowszym :) Tak myślałem, że jakiś antyk jest na tapecie, a antyki miały spore problemy z RTTI (i generykami) ;-) W Tokyo (i kilku wersjach wstecz) to działa, bo niby czemu nie? -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 11:42
Date: Fri, 25 Jan 2019 11:42
32 lines
1032 bytes
1032 bytes
On Fri, 25 Jan 2019 01:34:15 -0800 (PST), immo wrote: >>> Ten problem konkretnie w Delphi XE2, ale nakierowałeś mnie - muszę to sprawdzić w najnowszym :) >> >> Tak myślałem, że jakiś antyk jest na tapecie, a antyki miały spore problemy >> z RTTI (i generykami) ;-) >> >> W Tokyo (i kilku wersjach wstecz) to działa, bo niby czemu nie? > > Jesteś pewien że działa? Właśnie sprawdziłem w RIO i jego źródłach i nie ma prawa działać :P procedure test; var ctx : TRttiContext; rttiType : TRttiType; rttiProp : TRttiProperty; value: variant; rttiValue: TValue; Begin Value := 1; rttiValue := TValue.FromVariant(Value); // ShowMessage(rttiValue.ToString); //tutaj pokazuje poprawne wartości ctx := TRttiContext.Create; rttitype := ctx.GetType(frmMain.cbbServerAddress.ClassInfo); rttiprop := rttitype.GetProperty('ItemIndex'); rttiProp.SetValue(frmMain.cbbServerAddress, rttiValue); end; Taki kod przestawia mi itemindex z 0 na 1. Bez błędów i problemów. -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 11:49
Date: Fri, 25 Jan 2019 11:49
28 lines
905 bytes
905 bytes
On Fri, 25 Jan 2019 11:42:37 +0100, Roman Tyczka wrote: >> Jesteś pewien że działa? Właśnie sprawdziłem w RIO i jego źródłach i nie ma prawa działać :P > > procedure test; > var > ctx : TRttiContext; > rttiType : TRttiType; > rttiProp : TRttiProperty; > value: variant; > rttiValue: TValue; > Begin > Value := 1; > rttiValue := TValue.FromVariant(Value); > // ShowMessage(rttiValue.ToString); //tutaj pokazuje poprawne wartości > ctx := TRttiContext.Create; > rttitype := ctx.GetType(frmMain.cbbServerAddress.ClassInfo); > rttiprop := rttitype.GetProperty('ItemIndex'); > rttiProp.SetValue(frmMain.cbbServerAddress, rttiValue); > end; > > Taki kod przestawia mi itemindex z 0 na 1. Bez błędów i problemów. U Ciebie pewnie problemem jest metoda GetDBValueAsVariant, która robi Varianta integerowego jako stringowego. I stąd ambaras. -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 12:04
Date: Fri, 25 Jan 2019 12:04
16 lines
514 bytes
514 bytes
On Fri, 25 Jan 2019 11:49:31 +0100, Roman Tyczka wrote: >> Taki kod przestawia mi itemindex z 0 na 1. Bez błędów i problemów. > > U Ciebie pewnie problemem jest metoda GetDBValueAsVariant, która robi > Varianta integerowego jako stringowego. I stąd ambaras. Gdybyś w metodzie GetDBValueAsVariant, gdzie wiesz jakiego typu jest kolumna w taneli, uży do zwracania varianta czegoś takiego: result := TValue.From<ColumnType>(DBValue).AsVariant to problemy by zniknęły imho. -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 14:16
Date: Fri, 25 Jan 2019 14:16
38 lines
1208 bytes
1208 bytes
On Fri, 25 Jan 2019 04:34:47 -0800 (PST), immo wrote: >>>> Taki kod przestawia mi itemindex z 0 na 1. Bez błędów i problemów. >>> >>> U Ciebie pewnie problemem jest metoda GetDBValueAsVariant, która robi >>> Varianta integerowego jako stringowego. I stąd ambaras. >> >> Gdybyś w metodzie GetDBValueAsVariant, gdzie wiesz jakiego typu jest >> kolumna w taneli, uży do zwracania varianta czegoś takiego: >> >> result := TValue.From<ColumnType>(DBValue).AsVariant >> >> to problemy by zniknęły imho. > > No chyba nie :) W tabeli jest string, a jak pokazałem powyżej w kodzie w System.Rtti przy Convert dla tkString do tkInteger jest ConvFail :) Sprawdziłem ten kod, działa: procedure test; var ctx : TRttiContext; rttiType : TRttiType; rttiProp : TRttiProperty; value: variant; rttiValue: TValue; v: Variant; Begin v := '5'; //czyli variant "stringowy" Value := TValue.From<Integer>(v).AsVariant; rttiValue := TValue.FromVariant(Value); ctx := TRttiContext.Create; rttitype := ctx.GetType(frmMain.cbbServerAddress.ClassInfo); rttiprop := rttitype.GetProperty('ItemIndex'); rttiProp.SetValue(frmMain.cbbServerAddress, rttiValue); end; -- pozdrawiam Roman Tyczka
Re: RTTI SetValue i TValue.FromVariant
Author: Roman Tyczka
Date: Fri, 25 Jan 2019 15:27
Date: Fri, 25 Jan 2019 15:27
46 lines
1875 bytes
1875 bytes
On Fri, 25 Jan 2019 06:17:23 -0800 (PST), immo wrote: >> Value := TValue.From<Integer>(v).AsVariant; > > No tak zadziała to jawnie konwertujesz stringa do integera :) Podobne rozwiązanie podałem powyżej. > Natomiast chodzi o to, że jeśli TValue w środku ma varianta stringowego to nie potrafi go skonwertować do integera. I tyle. > Zastanawiam się tylko, czy jest jakiś powód takiego działania, czy po prostu zaniedbanie, błąd, czy może zostawione to jest na wieczne "później". > Bo mając informacje o tym jakiego rodzaju jest property, mając informacje jakiego rodzaju jest variant w TValue nie problem przekonwertować stringa do integera... Albo przerobić SetValue, zeby nie wymagał TValue tylko Varianta... Wynika to z tego, że TValue nie jest odpowiednikiem Varianta czyli typu autokonwertującego, TValue służy do wewnętrzbych spraw RTTI jako kontener na wartość. > Wiem że varianty są kapryśne w niektórych zastosowaniach - może to jest problemem dlaczego to jest tak a nie inaczej? > > Zresztą - nieważne - to już tylko dywagacje na ten temat :) To jeszcze ostatni kodzik, tym razem bazuje na typie docelowym, który bierze z propertysa i też robi konwersję tylko bez żadnych case of: procedure test; var ctx : TRttiContext; rttiType : TRttiType; rttiProp : TRttiProperty; value: variant; rttiValue: TValue; v: Variant; Begin v := '5'; ctx := TRttiContext.Create; rttitype := ctx.GetType(frmMain.cbbServerAddress.ClassInfo); rttiProp := rttitype.GetProperty('ItemIndex'); value := rttiProp.GetValue(frmMain.cbbServerAddress).AsVariant; value := VarAsType(v, VarType(value)); rttiValue := TValue.FromVariant(value); rttiProp.SetValue(frmMain.cbbServerAddress, rttiValue); end; > pozdrawiam i miłego weekendu, pozdrawiam także życząc spokoju i odpoczynku -- pozdrawiam Roman Tyczka
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads