如何使用运行时类型信息(RTTI)来获取一个类的正确构造函数?

3
我正在使用Delphi中定义的一个类进行工作,该类如下所示:
type
  TMyObject = class(TObject)
    constructor Create(a: string); overload; virtual;
    constructor Create(b: integer); overload; virtual;
  end;

我需要使用RTTI检索TMyObject的构造函数列表。我尝试使用TRttiType实例的GetMethods('Create')函数来实现:
var
  Context: TRttiContext;
  RttiType: TRttiType;
  Method: TRttiMethod;
begin
  Context := TRttiContext.Create;
  RttiType := Context.GetType(TMyObject);
  for Method in RttiType.GetMethods('Create') do
  begin
    // Process method
  end;

然而,我发现GetMethods('Create')也会返回从TObject继承的Create方法,这对于创建TMyObject实例来说是不合适的,因为TMyObject的构造函数中有额外的参数。
我该如何使用RTTI只获取可用于创建TMyObject实例的TMyObject构造函数?换句话说,我想排除从TObject或其他祖先继承的不能正确初始化TMyObject的构造函数。是否有办法使用RTTI识别和过滤掉这些不合适的构造函数?
非常感谢您提供任何指导或建议。
1个回答

2

就像你注意到的那样,TRttiType中的GetMethods函数会收集类层次结构中的所有方法。

但是,TRttiType中还有另一个方法GetDeclaredMethods,它只会检索特定类型中声明的方法,并且不会遍历祖先列表。然而,这个函数没有一个参数可以让你按名称过滤方法,所以为了得到你需要的结果,你需要编写额外的过滤函数。

类似于:

function GetDeclaredMethods(AType: TRttiType; const AName: string): TArray<TRttiMethod>;
var
  Methods: TArray<TRttiMethod>;
  Method: TRttiMethod;
begin
  SetLength(Result, 0);
  Methods := AType.GetDeclaredMethods;
  for Method in Methods do
    begin
      if Method.HasName(AName) then
        begin
          SetLength(Result, Length(Result) + 1);
          Result[High(Result)] := Method;
        end;
    end;
end;

在上述函数中添加方法并不是优化的,因此您可能想要优化该部分,但除非在类中声明了大量具有相同名称的重载方法,否则也不是极其低效。

4
在这种情况下,由于OP只对构造函数感兴趣,枚举可以根据TRttiMethod.IsConstructor来进行过滤,而不仅仅是根据名称。另外,构造函数也可以重命名为CreateByString()CreateByInt(),然后使用标准的TRttiType.GetMethod()方法即可。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接