1

I am using Delphi 10.1 Berlin update 2. Following is the code that reproduces the problem:

uses
  System.SysUtils,
  Rtti;

type
  TEnum = (t1, t2);
  TIndexedEnum  = (to1=1, to2);

  TClass1 = class
    constructor Create(pEnum: TEnum);
  end;

  TClass2 = class
    constructor Create(pEnum: TIndexedEnum);
  end;

constructor TClass1.Create(pEnum: TEnum);
begin
end;

constructor TClass2.Create(pEnum: TIndexedEnum);
begin
end;

function MethodParamCount(pMethodName: String; pClass: TClass): Integer;
var
  rContext: TRttiContext;
  rType: TRttiType;
  FMethods: TArray<TRttiMethod>;
  I: Integer;
begin
  rContext := TRttiContext.Create;
  rType := rContext.GetType(pClass);

  FMethods := rType.GetMethods;
  for I := Low(FMethods) to High(FMethods) do
    if SameText(pMethodName, FMethods[I].Name) then
    begin
      Result := Length(FMethods[I].GetParameters);
      Exit;
    end;
  Result := -1;
end;

begin
  WriteLn(IntToStr(MethodParamCount('Create', TClass1))); // Prints 1
  WriteLn(IntToStr(MethodParamCount('Create', TClass2))); // Prints 0
  ReadLn;
end.

Is that a bug of the RTTI implementation, or I am missing something? Is there a way to circumvent this issue without changing the class implementation?

Edit: I want to find a constructor without any parameters so I can call it using Invoke(). The thing is, RTTI is telling me there are no parameters for a method that actually has a parameter.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 5
    Probably related to the fact that enums that don't start with 0 and/or are discontiguous have no RTTI – Stefan Glienke Apr 29 '20 at 19:26
  • 1
    related: https://marc.durdin.net/2014/03/generics-and-delphi-enumerated-types-without-rtti/ – whosrdaddy Apr 29 '20 at 19:31
  • 1
    "*This example works with RTTI types, and with **one byte** non-RTTI enumerated types - **you’d need to extend it to support larger enumerated types**.*" - indeed, as enums are not limited to just 1 byte in size, they can be up to 4 bytes in size, depending on values used and compiler settings. – Remy Lebeau Apr 29 '20 at 20:04
  • @whosrdaddy That's an interesting workaround, but on my case I want to find a constructor without any parameters so I can call it using invoke. The thing is RTTI is telling me there is no parameters for a method that actually has a parameter. – Marcelo Rauter Apr 29 '20 at 20:19
  • 1
    @MarceloRauter: I know you said you don't want to change the class implementation, but what about adding a [method attribute](https://stackoverflow.com/a/22954821/800214) (only for the case where you don't get RTTI) for to the class telling what type of enum you would have to use to create the class correctly via RTTI Invoke? – whosrdaddy Apr 29 '20 at 22:04
  • @whosrdaddy What I am doing is a ORM framework and one of the main ideas is to be able to map any object with no change to the original class if possible. There is a dedicated DAO class where all the mapping will be configured. A custom construction can be implemented in this DAO, but it would be nice to be able to call the default constructor, if it exists; – Marcelo Rauter Apr 29 '20 at 22:43
  • 1
    @MarceloRauter "*I want to find a constructor without any parameters*" - and what about a constructor that has 1 or more parameters, and all of the parameters have default values? That is also considered a "default constructor". Any constructor that you don't have to pass an *explicit* parameter value to is a "default constructor" – Remy Lebeau Apr 30 '20 at 05:26
  • 1
    @MarceloRauter: you might want to take a look at the source code for [Spring4D](https://bitbucket.org/sglienke/spring4d/src/master/) (a depency injection framework) – whosrdaddy Apr 30 '20 at 09:17
  • @RemyLebeau You are right, in theory it would be nice to check for constructors with no parameters or that have parameters with default value only, but I don't think I can check for default values on method parameters with RTTI, am I right? – Marcelo Rauter Apr 30 '20 at 11:35
  • @whosrdaddy Yes I know Spring4D and it is amazing. I took a look at Marshmallow, the ORM part of spring I am pretty sure it relies on generics to create instances. I think I will have to adapt my code to do the same. – Marcelo Rauter Apr 30 '20 at 11:44

0 Answers0