jairgza 0 Posted August 22, 2021 Hi From TForm1 object I need to know the GUID of ITestA from field MyField. But the field is an anonymous function that I try to use a a lazy loading logic type ITestA = interface ['{0BE93958-EAC8-429B-A498-221B93328551}'] end; TForm1 = class(TForm) private MyField:TFunc<ITestA>; end; Using RTTI can investigate TForm1 class and "MyField" is recognized as TRttiInterfaceType but the GUID property returns {00000000-0000-0000-0000-000000000000} TRttiInterfaceType(rf.FieldType).GUID.ToString is there any way to achieve this ? regards Share this post Link to post
Dave Nottage 552 Posted August 22, 2021 1 hour ago, jairgza said: Using RTTI can investigate TForm1 class and "MyField" is recognized as TRttiInterfaceType Can you show how you're querying MyField? Share this post Link to post
jairgza 0 Posted August 23, 2021 procedure TForm1.Button1Click(Sender: TObject); var ctx:TRttiContext; rf:TRttiField; begin //test ctx := TRttiContext.Create; rf := ctx.GetType(Self.ClassType).GetField('MyField'); if rf.FieldType is TRttiInterfaceType then begin Log('GUID: '+ TRttiInterfaceType(rf.FieldType).GUID.ToString ); Log('GUID: '+ rf.FieldType.Handle.TypeData.GUID.ToString ); end; end; Hi, this is the test code Delphi 10.2 win10 Share this post Link to post
Dalija Prasnikar 1392 Posted August 23, 2021 TFunc is anonymous method, which are backed by interface. So GUID you get from field type is not for ITestA,, but for TFunc<ITestA>. I don't think you can get generic part out from parameterized type. In theory TFunc has Invoke method, so if you could get information on its result type, you would have ITestA. But I couldn't get Invoke information out of RTTI. The real question here is what you are actually trying to do. Your test code is obviously just a test - you already know that TForm1 MyField works with ITestA, so if you can make small test case for your actual use case, maybe there is a way to get information you need. For instance if your form would be generic, you would more easily get what you need because you would have T to work with TForm1<T> = class(TForm) private MyField:TFunc<T>; end; 1 Share this post Link to post
Remy Lebeau 1376 Posted August 23, 2021 (edited) Quote I don't think you can get generic part out from parameterized type. There is nothing in the RTTI system for that purpose, no. You would have to manually parse the TRttiField.FieldType.QualifiedName of the field in question (in this case, yielding 'TFunc<ITestA>') to extract what is between the brackets ('ITestA'), and then get the TRttiType of that type from TRttiContext and typecast it to TRttiInterfaceType to get its GUID. Quote For instance if your form would be generic, you would more easily get what you need because you would have T to work with TForm1<T> = class(TForm) private MyField:TFunc<T>; end; Except that you can't use Generic types for DFM-streamable classes. The DFM system doesn't handle Generic class types. Edited August 23, 2021 by Remy Lebeau Share this post Link to post
jairgza 0 Posted August 25, 2021 Quote There is nothing in the RTTI system for that purpose, no. You would have to manually parse the TRttiField.FieldType.QualifiedName That's what I did, extract the string name of the interface and search in my interface list. Quote The real question here is what you are actually trying to do. Just experimenting with rtti and trying to do some kind of dependency injection, try to inject a generic function that actually return the object when is used (Lazy loading). Thanks for your comments Share this post Link to post
Stefan Glienke 1996 Posted August 25, 2021 11 minutes ago, jairgza said: trying to do some kind of dependency injection, try to inject a generic function that actually return the object when is used (Lazy loading). If your experiments are not just for educational purposes try out Spring - the container can do exactly that. Share this post Link to post
Walter Verhoeven 4 Posted April 17 Lots of talk not much code... Here is my test type IImplementsStuff = interface(IInterface) ['{83B3CBFA-9854-4BFC-A7B3-A015BE6B8B0B}'] // Interface methods end; [TestFixture] StringUtilsTests = class public [Test] procedure InterFaceToGuid; end; implementation uses SysUtils; procedure StringUtilsTests.InterFaceToGuid; var GUIDStr: string; begin GUIDStr := GetInterfaceGUID(TypeInfo(IImplementsStuff)); Assert.AreEqual('{83B3CBFA-9854-4BFC-A7B3-A015BE6B8B0B}',GUIDStr); end; Here is my implementation: function GetInterfaceGUID(const TypeInfo: PTypeInfo): string; var TypeData: PTypeData; GUID: TGUID; begin Result := ''; if TypeInfo.Kind = tkInterface then begin TypeData := GetTypeData(TypeInfo); // Correctly handle the conversion from byte array to TGUID Move(TypeData.IntfGuid, GUID, SizeOf(TGUID)); Result := GUIDToString(GUID); end else raise Exception.Create('Provided type is not an interface'); end; Hope it helps you as well as anyone else who needs it 1 Share this post Link to post
Stefan Glienke 1996 Posted April 22 That code only works for Delphi 10.2 and later - the proper way would be to simply write GUID := TypeData.Guid; Share this post Link to post