Search code examples
delphifiremonkeyrtti

Runtime creation of Delphi Firemonkey components from a string


How can i create at runtime a visual component as a child of the form using eventually RTTI? All i got is a TValue instance...

 t := (ctx.FindType(Edit1.Text) as TRttiInstanceType);
 inst:= t.GetMethod('Create').Invoke(t.MetaclassType,[Form1]);

Thank you!


Solution

  • A purely RTTI approach using TRttiMethod.Invoke() would look something like this:

    var
      ctx: TRttiContext;
      t: TRttiInstanceType;
      m: TRttiMethod;
      params: TArray<TRttiParameter>;
      v: TValue;
      inst: TControl;
    begin
      t := ctx.FindType(Edit1.Text) as TRttiInstanceType;
      if t = nil then Exit;
      if not t.MetaclassType.InheritsFrom(TControl) then Exit;
      for m in t.GetMethods('Create') do
      begin
        if not m.IsConstructor then Continue;
        params := m.GetParameters;
        if Length(params) <> 1 then Continue;
        if params[0].ParamType.Handle <> TypeInfo(TComponent) then Continue;
        v := m.Invoke(t.MetaclassType, [TComponent(Form1)]);
        inst := v.AsType<TControl>();
        // or: inst := TControl(v.AsObject);
        Break;
      end;
      inst.Parent := ...;
      ...
    end;
    

    A much simpler approach that does not use TRttiMethod.Invoke() would look like this:

    type
      // TControlClass is defined in VCL, but not in FMX
      TControlClass = class of TControl;
    
    var
      ctx: TRttiContext;
      t: TRttiInstanceType;
      inst: TControl;
    begin
      t := ctx.FindType(Edit1.Text) as TRttiInstanceType;
      if t = nil then Exit;
      if not t.MetaclassType.InheritsFrom(TControl) then Exit;
      inst := TControlClass(t.MetaclassType).Create(Form4);
      inst.Parent := ...;
      //...
    end;