Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2022-12

Unrelated type helpers with the same members? Implement an interface with a type helper?

11 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andrew Haines

Hi what I want to do is similar to this question here: https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/

I am going to create multiple type helpers for enums and I would like to look up the helper and use common methods AsString AsOrdinal to get/set the values. I am recieving them as json that I dont have control over. I am using typeinfo to fill in all the properties but I would like to convert the strings I am receiving to the enum values semi-automatically.

LString := 'STATUS';
LHelper := GetHelper(LPropInfo^.PropType); // enum proptype
LToStringInterface := LHelper as IToStringInterface;
SetOrdProp(LObject, 'propname', LToStringInterface.OrdValue(LString);

Something like that. I'm not sure if it's even possible to find the helper type with typeinfo.

Thanks for your suggestions :)

Regards,

Andrew

Reply by email

Andrew Haines
to Andrew Haines

So, I came up with a solution using Custom Attributes.

I can declare this:

[TEnumAttr('YES', 'NO', 'COULD_BE')]
   TMyEnum = (meYes, meNo, meCouldBe);

and at runtime look for the TEnumAttr attribute and use that.

TEnumAttr = class(TCustomAttribute)
   protected
     FValues: TStringArray;
     FTypeName: String;
   public
     class function FromType(ATypeInfo: PTypeInfo): TEnumAttr;
     constructor Create(Val1: String);
     constructor Create(Val1, Val2: String);

etc

Maybe this can help someone else with a similar use case.

Regards,

Andrew Haines

Andrew Haines wrote 31 lines
Hi what I want to do is similar to this question here: https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ I am going to create multiple type helpers for enums and I would like to look up the helper and use common methods AsString AsOrdinal to get/set the values. I am recieving them as json that I dont have control over. I am using typeinfo to fill in all the properties but I would like to convert the strings I am receiving to the enum values semi-automatically. LString := 'STATUS'; LHelper := GetHelper(LPropInfo^.PropType); // enum proptype LToStringInterface := LHelper as IToStringInterface; SetOrdProp(LObject, 'propname', LToStringInterface.OrdValue(LString); Something like that. I'm not sure if it's even possible to find the helper type with typeinfo. Thanks for your suggestions :) Regards, Andrew _______________________________________________ fpc-pascal maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Andrew Haines: Hi what I want to do is similar to this question here:…
Andrew Haines wrote 12 lines
Hi what I want to do is similar to this question here: https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ I am going to create multiple type helpers for enums and I would like to look up the helper and use common methods AsString AsOrdinal to get/set the values. I am recieving them as json that I dont have control over. I am using typeinfo to fill in all the properties but I would like to convert the strings I am receiving to the enum values semi-automatically. LString := 'STATUS'; LHelper := GetHelper(LPropInfo^.PropType); // enum proptype

Since there can be multiple type helpers for a type, this will never be possible. At best you would get a list.

But I don't think there is even a list of type helpers per type. Sven will need to confirm.

In your case, I would simply register a function that does this for each known enum type.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt

Michael Van Canneyt via fpc-pascal
schrieb am Fr., 23. Dez. 2022, 08:18:

Show quoted text 26 lines
On Thu, 22 Dec 2022, Andrew Haines via fpc-pascal wrote: > Hi what I want to do is similar to this question here: > https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ > > I am going to create multiple type helpers for enums and I would like to look > up the helper and use common methods AsString AsOrdinal to get/set the > values. I am recieving them as json that I dont have control over. I am using > typeinfo to fill in all the properties but I would like to convert the > strings I am receiving to the enum values semi-automatically. > > LString := 'STATUS'; > > LHelper := GetHelper(LPropInfo^.PropType); // enum proptype Since there can be multiple type helpers for a type, this will never be possible. At best you would get a list. But I don't think there is even a list of type helpers per type. Sven will need to confirm.

As the active helper(s) for a type change(s) depending on the current scope (e.g. in unit A it might be a different helper than in unit B) this is not possible. Also helpers are not in any way usable on their own except to retrieve their RTTI information.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 34 lines
Michael Van Canneyt via fpc-pascal schrieb am Fr., 23. Dez. 2022, 08:18: > > > On Thu, 22 Dec 2022, Andrew Haines via fpc-pascal wrote: > >> Hi what I want to do is similar to this question here: >> > https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ >> >> I am going to create multiple type helpers for enums and I would like to > look >> up the helper and use common methods AsString AsOrdinal to get/set the >> values. I am recieving them as json that I dont have control over. I am > using >> typeinfo to fill in all the properties but I would like to convert the >> strings I am receiving to the enum values semi-automatically. >> >> LString := 'STATUS'; >> >> LHelper := GetHelper(LPropInfo^.PropType); // enum proptype > > Since there can be multiple type helpers for a type, this will never be > possible. At best you would get a list. > > But I don't think there is even a list of type helpers per type. > Sven will need to confirm. > As the active helper(s) for a type change(s) depending on the current scope (e.g. in unit A it might be a different helper than in unit B) this is not possible. Also helpers are not in any way usable on their own except to retrieve their RTTI information.

But theoretically it should be possible to generate and get a list of all defined type helpers, whether they are in scope or not ?

If their RTTI could include a function that returns an interface, you could retrieve that and do as the OP suggests...

I think the OP's solution with attributes is the same as the one TMS Software's Aurelius ORM uses.

Michael.

Reply by email

Ondrej Pokorny
to Andrew Haines: So, I came up with a solution using Custom Attributes. I can declare this:…

This may be simpler:

[TEnumAttr(['YES', 'NO', 'COULD_BE'])]
   TMyEnum = (meYes, meNo, meCouldBe);
TEnumAttr = class(TCustomAttribute)
   protected
     FValues: TStringArray;
     FTypeName: String;
   public
     class function FromType(ATypeInfo: PTypeInfo): TEnumAttr;
     constructor Create(Values: array of string);

---

Or, if the enum values are valid identifiers, you can simple use scoped enums:

{$SCOPEDENUMS ON}
   TMyEnum = (YES, NO, COULD_BE);

and the usual TypeInfo methods.

Ondrej

Andrew Haines wrote 63 lines
So, I came up with a solution using Custom Attributes. I can declare this: [TEnumAttr('YES', 'NO', 'COULD_BE')]   TMyEnum = (meYes, meNo, meCouldBe); and at runtime look for the TEnumAttr attribute and use that. TEnumAttr = class(TCustomAttribute)   protected     FValues: TStringArray;     FTypeName: String;   public     class function FromType(ATypeInfo: PTypeInfo): TEnumAttr;     constructor Create(Val1: String);     constructor Create(Val1, Val2: String); etc Maybe this can help someone else with a similar use case. Regards, Andrew Haines On 12/22/22 8:40 PM, Andrew Haines via fpc-pascal wrote: > Hi what I want to do is similar to this question here: > https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ > > I am going to create multiple type helpers for enums and I would like > to look up the helper and use common methods AsString AsOrdinal to > get/set the values. I am recieving them as json that I dont have > control over. I am using typeinfo to fill in all the properties but I > would like to convert the strings I am receiving to the enum values > semi-automatically. > > LString := 'STATUS'; > > LHelper := GetHelper(LPropInfo^.PropType); // enum proptype > > LToStringInterface := LHelper as IToStringInterface; > > SetOrdProp(LObject, 'propname', LToStringInterface.OrdValue(LString); > > > Something like that. I'm not sure if it's even possible to find the > helper type with typeinfo. > > Thanks for your suggestions :) > > Regards, > > Andrew > > _______________________________________________ > fpc-pascal maillist  -  > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal _______________________________________________ fpc-pascal maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Sven Barth
to Michael Van Canneyt: But theoretically it should be possible to generate and get a list of all defined type…

Michael Van Canneyt via fpc-pascal
schrieb am Fr., 23. Dez. 2022, 10:48:

Show quoted text 46 lines
On Fri, 23 Dec 2022, Sven Barth via fpc-pascal wrote: > Michael Van Canneyt via fpc-pascal > schrieb am Fr., 23. Dez. 2022, 08:18: > >> >> >> On Thu, 22 Dec 2022, Andrew Haines via fpc-pascal wrote: >> >>> Hi what I want to do is similar to this question here: >>> >> https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ >>> >>> I am going to create multiple type helpers for enums and I would like to >> look >>> up the helper and use common methods AsString AsOrdinal to get/set the >>> values. I am recieving them as json that I dont have control over. I am >> using >>> typeinfo to fill in all the properties but I would like to convert the >>> strings I am receiving to the enum values semi-automatically. >>> >>> LString := 'STATUS'; >>> >>> LHelper := GetHelper(LPropInfo^.PropType); // enum proptype >> >> Since there can be multiple type helpers for a type, this will never be >> possible. At best you would get a list. >> >> But I don't think there is even a list of type helpers per type. >> Sven will need to confirm. >> > > As the active helper(s) for a type change(s) depending on the current scope > (e.g. in unit A it might be a different helper than in unit B) this is not > possible. Also helpers are not in any way usable on their own except to > retrieve their RTTI information. But theoretically it should be possible to generate and get a list of all defined type helpers, whether they are in scope or not ?

No, because the compiler doesn't keep track of that. It's only interested in what is in scope *right now*.

If their RTTI could include a function that returns an interface, you could retrieve that and do as the OP suggests..

Don't make helpers to something that they're simply not there for.

Regards,
Sven

Reply by email

Andrew Haines
to Ondrej Pokorny: This may be simpler: [TEnumAttr(['YES', 'NO', 'COULD_BE'])]   TMyEnum = (meYes, meNo,…
Ondrej Pokorny wrote 14 lines
This may be simpler: [TEnumAttr(['YES', 'NO', 'COULD_BE'])]   TMyEnum = (meYes, meNo, meCouldBe); TEnumAttr = class(TCustomAttribute)   protected     FValues: TStringArray;     FTypeName: String;   public     class function FromType(ATypeInfo: PTypeInfo): TEnumAttr;     constructor Create(Values: array of string); ---

I tried that first but the compiler gave an error on the "["

Error: Ordinal expression expected

[TEnumAttr(['YES', 'NO', 'COULD_BE'])]

Show quoted text 12 lines
Or, if the enum values are valid identifiers, you can simple use scoped enums: {$SCOPEDENUMS ON}   TMyEnum = (YES, NO, COULD_BE); and the usual TypeInfo methods. Ondrej

I didn't know about those, that could also be a good solution, thanks!

Andrew

Reply by email

Michael Van Canneyt
to Sven Barth: Michael Van Canneyt via fpc-pascal schrieb am Fr., 23. Dez. 2022, 10:48: No, because the…
Sven Barth wrote 52 lines
Michael Van Canneyt via fpc-pascal schrieb am Fr., 23. Dez. 2022, 10:48: > > > On Fri, 23 Dec 2022, Sven Barth via fpc-pascal wrote: > >> Michael Van Canneyt via fpc-pascal >> schrieb am Fr., 23. Dez. 2022, 08:18: >> >>> >>> >>> On Thu, 22 Dec 2022, Andrew Haines via fpc-pascal wrote: >>> >>>> Hi what I want to do is similar to this question here: >>>> >>> > https://en.delphipraxis.net/topic/423-rtti-determine-record-helper-type-for-a-base-type/ >>>> >>>> I am going to create multiple type helpers for enums and I would like > to >>> look >>>> up the helper and use common methods AsString AsOrdinal to get/set the >>>> values. I am recieving them as json that I dont have control over. I am >>> using >>>> typeinfo to fill in all the properties but I would like to convert the >>>> strings I am receiving to the enum values semi-automatically. >>>> >>>> LString := 'STATUS'; >>>> >>>> LHelper := GetHelper(LPropInfo^.PropType); // enum proptype >>> >>> Since there can be multiple type helpers for a type, this will never be >>> possible. At best you would get a list. >>> >>> But I don't think there is even a list of type helpers per type. >>> Sven will need to confirm. >>> >> >> As the active helper(s) for a type change(s) depending on the current > scope >> (e.g. in unit A it might be a different helper than in unit B) this is > not >> possible. Also helpers are not in any way usable on their own except to >> retrieve their RTTI information. > > But theoretically it should be possible to generate and get a list of all > defined type helpers, whether they are in scope or not ? > No, because the compiler doesn't keep track of that. It's only interested in what is in scope *right now*.

I understand such a list is not kept now.
That's why I said "theoretically" as in "it is possible to add to the compiler"

To be clear:
I don't think you should add such a list, I'm simply interested in the possibility of such a thing.

Michael.

Reply by email

Ondrej Pokorny
to Andrew Haines: I tried that first but the compiler gave an error on the "[" Error: Ordinal expression…
Andrew Haines wrote 18 lines
On 12/23/22 5:24 AM, Ondrej Pokorny via fpc-pascal wrote: > This may be simpler: > > [TEnumAttr(['YES', 'NO', 'COULD_BE'])] >   TMyEnum = (meYes, meNo, meCouldBe); > > TEnumAttr = class(TCustomAttribute) >   protected >     FValues: TStringArray; >     FTypeName: String; >   public >     class function FromType(ATypeInfo: PTypeInfo): TEnumAttr; >     constructor Create(Values: array of string); I tried that first but the compiler gave an error on the "[" Error: Ordinal expression expected [TEnumAttr(['YES', 'NO', 'COULD_BE'])]

Indeed. I would say that is a bug and therefore I reported it: https://gitlab.com/freepascal.org/fpc/source/-/issues/40058

I usually use the scoped enums but in case the enum values are not valid identifiers this is the perfect way to handle them. Therefore thanks for the idea :) I use attributes for various things but didn't realize this possibility.

Ondrej

Reply by email