I have a problem with the properties of IInterface type. I don't know how to assign values to these properties using RTTI
Here's an example:.
program Project2;
uses
  Forms, RTTI, Windows, TypInfo;
{$R *.res}
type
  ITestInterfacedClass = interface
    ['{25A5B554-667E-4FE4-B932-A5B8D9052A17}']
    function GetA: ITestInterfacedClass;
    procedure SetA(const Value: ITestInterfacedClass);
    property A: ITestInterfacedClass read GetA write SetA;
    function GetB: ITestInterfacedClass;
    procedure SetB(const Value: ITestInterfacedClass);
    property B: ITestInterfacedClass read GetB write SetB;
  end;
  TTestInterfacedClass = class(TInterfacedObject, ITestInterfacedClass)
  private
    FA: ITestInterfacedClass;
    FB: ITestInterfacedClass;
    function GetA: ITestInterfacedClass;
    function GetB: ITestInterfacedClass;
    procedure SetA(const Value: ITestInterfacedClass);
    procedure SetB(const Value: ITestInterfacedClass);
  public
    property A: ITestInterfacedClass read GetA write SetA;
    property B: ITestInterfacedClass read GetB write SetB;
  end;
  { ITestInterfacedClass }
....
procedure SetProperty(aLeft: TObject {IInterface}; aNameProp: string; aRight: IInterface);
var
  RttiContext: TRttiContext;
  RttiType: TRttiType;
  RTTIProperty: TRttiProperty;
begin
  RttiContext := TRttiContext.Create;
  RTTIType := RttiContext.GetType(TTestInterfacedClass);
  RTTIProperty := RTTIType.GetProperty(aNameProp);
  if RTTIProperty.PropertyType.TypeKind = tkInterface then
    RTTIProperty.SetValue(aLeft, TValue.From<IInterface>(aRight));
end;
var
  obj1: TTestInterfacedClass;
  intf1, intf2, intf3: ITestInterfacedClass;
begin
  obj1 := TTestInterfacedClass.Create;
  intf1 := obj1;
  intf2 := TTestInterfacedClass.Create;
  intf3 := TTestInterfacedClass.Create;
  intf1.A := intf2;
  // intf1.B := intf3;
  SetProperty(obj1, 'B', intf3);
end.
I have to write an analog of intf1.B: = intf3; or obj1.B = intf3;
using RTTI.
Is this possible?
UPD It is work:
procedure SetProperty(aLeft: TObject; aNameProp: string; aRight: IInterface);
var
  RttiContext: TRttiContext;
  RttiTypeInterface: TRttiInterfaceType;
  RTTIProperty: TRttiProperty;
  Value: TValue;
begin
  RttiContext := TRttiContext.Create;
  RTTIType := RttiContext.GetType(aLeft.ClassType);
  RTTIProperty := RTTIType.GetProperty(aNameProp);
  if RTTIProperty.PropertyType.TypeKind = tkInterface then
  begin
    TValue.Make(@aRight, RTTIProperty.PropertyType.Handle, Value);
    RTTIProperty.SetValue(aLeft, Value);
  end;
end;
                Unfortunately, that doesn't work because the Interface conversion code in RTTI.pas doesn't call QueryInterface.  If you put a TValue in with TValue.From<IInterface>, you can't convert it to a TValue of a different interface type, even if the interface supports that type.  Feel free to submit that to QC.
Creating the TValue with TValue.From<ITestInterfacedClass> does work, though.  But then you can't use the simple SetProperty routine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With