Recent

Author Topic: [SOLVED] Call method with RTTI  (Read 1493 times)

StraightFree

  • New Member
  • *
  • Posts: 38
[SOLVED] Call method with RTTI
« on: April 08, 2023, 05:28:36 pm »
Hello,

I'm developing a ORM with lazarus 2.24 and FPC 3.2.2 using RTTI and all functionallity working. I create database, create table, create columns, create index and so on. I developing in linux and use cross-compile to linux and windows.
Now I want create some records in database. To do this I create a method SeedData in model class that I need records default. My model class is like this:

Code: Pascal  [Select][+][-]
  1. type
  2.    TUser = class(TObject)
  3.         private
  4.             FName: string;
  5.         public
  6.             procedure SeedData;
  7.         published
  8.             property Name: string read FName write FName;
  9.    end;
  10.  
  11. procedure TUser.SeedData;
  12. begin
  13. //here the method to insert data
  14. end;


So, after the ORM create the database and table, I need that ORM call this function, if this is declared in model class.
I tried some codes, but everytime my TRTTIMethod is nil.

Someone has any sugestion to call this method?

Any help in welcome.

Thanks for help
« Last Edit: April 11, 2023, 07:31:21 pm by StraightFree »

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Re: Call method with RTTI
« Reply #1 on: April 08, 2023, 05:53:11 pm »
I tried some codes, but everytime my TRTTIMethod is nil.

Currently TRTTIMethod is only non-Nil for methods declared as published. Any other visibility requires Extended RTTI which is not yet available.

Suggestions:
  • declare your SeedData as published (don't forget to mark your types with $M+ or derive from a class that has that mark)
  • derive your data types from a base type that provides the SeedData method
  • implement an interface (probably a raw interface instead of a reference counted one, cause in the later case you should derive from TInterfacedObject or some class that implements the IInterface methods and then you could just use the above point of a custom base class)

StraightFree

  • New Member
  • *
  • Posts: 38
Re: Call method with RTTI
« Reply #2 on: April 08, 2023, 06:04:56 pm »
PascalDragom,

Thanks for your reply.

1 - You first suggestion I tried too. But my TRTTIMethod is nil again.
2 - The second point, in truth, I simplify my question and my TUser class is based in the class TModelBase. But I dont want put method in TModelBase, because I dont need that method is called in all class. So this is extremally necessary?
3 - I dont have much experience in Interface. So, do you have any exemple for this?

Thanks

jamie

  • Hero Member
  • *****
  • Posts: 7660
Re: Call method with RTTI
« Reply #3 on: April 08, 2023, 06:05:48 pm »
@StreightFree
   Just curious, what other languages, tools have you come from?
The only true wisdom is knowing you know nothing

StraightFree

  • New Member
  • *
  • Posts: 38
Re: Call method with RTTI
« Reply #4 on: April 08, 2023, 06:15:17 pm »
Hello jamie,

I program in PHP, javascript, java and c.
I know others languages but not suficient to mentione. kkk


jamie

  • Hero Member
  • *****
  • Posts: 7660
Re: Call method with RTTI
« Reply #5 on: April 08, 2023, 06:18:24 pm »
Ok, if you could show the partial of code that is expected to make the request call it would be nice, I think I could offer up a solution.
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Re: Call method with RTTI
« Reply #6 on: April 08, 2023, 06:45:25 pm »
1 - You first suggestion I tried too. But my TRTTIMethod is nil again.

Right... forgot that methods require Extended RTTI as well. Though you could use TObject.MethodAddress in that case...

2 - The second point, in truth, I simplify my question and my TUser class is based in the class TModelBase. But I dont want put method in TModelBase, because I dont need that method is called in all class. So this is extremally necessary?

You could create an additional sub class of TModelBase that provides the SeedData method...

3 - I dont have much experience in Interface. So, do you have any exemple for this?

Here you go.

Code: Pascal  [Select][+][-]
  1. program trttimeth;
  2.  
  3. {$mode objfpc}
  4.  
  5. type
  6.   {$Interfaces Corba}
  7.   ISeedDataIntf = interface
  8.     procedure SeedData;
  9.   end;
  10.  
  11.   TTest = class(TObject, ISeedDataIntf)
  12.   public
  13.     procedure SeedData;
  14.   end;
  15.  
  16. procedure TTest.SeedData;
  17. begin
  18.   Writeln('Foo');
  19. end;
  20.  
  21. var
  22.   obj: TObject;
  23.   test: TTest;
  24.   intf: ISeedDataIntf;
  25. begin
  26.   test := TTest.Create;
  27.   try
  28.     { to demonstrate that it works with a TObject as well }
  29.     obj := test;
  30.  
  31.     intf := obj as ISeedDataIntf;
  32.     intf.SeedData;
  33.   finally
  34.     test.Free;
  35.   end;
  36. end.

StraightFree

  • New Member
  • *
  • Posts: 38
Re: Call method with RTTI
« Reply #7 on: April 11, 2023, 07:25:48 pm »
jamie,

Thaks for your reply.

Sorry for delay to response.
I was used RTTI, but I use suggestion maked by PascalDragon and this appear more eficient than I dident do.

Now, the code is working:

Code: Pascal  [Select][+][-]
  1. function TDatabaseCreate.SeedTable(AModel: TClass): boolean;
  2. var
  3.    obj: TObject;
  4. begin
  5.   obj := AModel.Create;
  6.  
  7.   if obj is TModelBaseSeed then
  8.      TModelBaseSeed(obj).SeedData;
  9. end;          

StraightFree

  • New Member
  • *
  • Posts: 38
Re: Call method with RTTI
« Reply #8 on: April 11, 2023, 07:31:04 pm »
PascalDragon,

Thanks for suggestion, this working.

I tested both suggestions, created a new class and a use interface. So I opt to use a new class.

Now, my code is very simple:

 
Code: Pascal  [Select][+][-]
  1. function TDatabaseCreate.SeedTable(AModel: TClass): boolean;
  2. var
  3.    obj: TObject;
  4. begin
  5.   obj := AModel.Create;
  6.  
  7.   if obj is TModelBaseSeed then
  8.      TModelBaseSeed(obj).SeedData;
  9. end;    

I only use TModelBaseSeed when I need seed in that class.

Thaks for you solution

 

TinyPortal © 2005-2018