Home > Enterprise >  Accessing the TList class via RTTI
Accessing the TList class via RTTI

Time:06-21

I want to implement the Add method of a List type property. but i get of "Invalid class typecast" error. does anyone have an idea about this.

Company.pas

  TEmployes = class
  private
    FLastName: String;
    FFirstName: String;
  public
    property FirstName: String
      read FFirstName write FFirstName;
    property LastName: String
      read FLastName write FLastName;
  end;

  TContext = class
  private
    FEmployess: TList<TEmployes>;
  public
    constructor Create;
    destructor Destroy; override;
    property Employess: TList<TEmployes>
      read FEmployess write FEmployess;
  end;

Project1.pas

  var Context: TContext := TContext.Create;

  var rContext: TRttiContext := TRttiContext.Create;
  var rIns : TRttiInstanceType :=
    rContext.GetType(Context.ClassInfo) as TRttiInstanceType;

  for var prop in rIns.GetProperties do
  begin
    var method: TRttiMethod := prop.PropertyType.GetMethod('Add');
    var emp: TEmployes := TEmployes.Create;
    emp.FirstName := 'Username';
    method.Invoke(prop.ClassInfo, [emp]);
  end;

  Context.Free;

CodePudding user response:

You didn't indicate which line of code is throwing the error.

But, the way you are using RTTI to access and invoke the TList<T>.Add() method is definitely wrong. You are basically invoking RTTI to perform the equivalent of the following:

for (<Every Property in TContext>) do
begin
  var emp: TEmployes := TEmployes.Create;
  emp.FirstName := 'Username';
  TList<TEmployes>(TRttiProperty.ClassInfo).Add(emp);
end;

What you really need to invoke is the equivalent of the following instead:

var Context: TContext := TContext.Create;

for (However Many Employees you need) do
begin
  var emp: TEmployes := TEmployes.Create;
  emp.FirstName := 'Username';
  Context.Employess.Add(emp);
end;

Context.Free;

That means you need to actually read the Employess property of the Context object to get its TList object, and then you can call Add() on that TList object, eg:

var Context: TContext := TContext.Create;

var rContext: TRttiContext := TRttiContext.Create;
var rIns : TRttiType := rContext.GetType(Context.ClassInfo);

var prop : TRttiProperty := rIns.GetProperty('Employess');
var method: TRttiMethod := prop.PropertyType.GetMethod('Add');
var list : TObject := prop.GetValue(Context).AsObject;

for (However Many Employees you need) do
begin
  var emp: TEmployes := TEmployes.Create;
  emp.FirstName := 'Username';
  method.Invoke(list, [emp]);
end;

Context.Free;
  • Related