Delphi 2010中的RTTI和接口字段

6

我在处理IInterface类型的属性时遇到了问题。我不知道如何使用RTTI为这些属性赋值。

以下是一个示例:

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.

我需要用RTTI写一个类似于intf1.B := intf3;或obj1.B = intf3;的模拟。

这是可能的吗?

更新:这是可行的:

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;

RTTIProperty.SetValue(aLeft, TValue.From<ITestInterfacedClass>(aRight as ITestInterfacedClass));这段代码是可以工作的,但在SetProperty中,我不想从ITestInterfacedClass中获取任何信息。 - Mielofon
1个回答

2
很遗憾,这不起作用是因为RTTI.pas中的接口转换代码没有调用QueryInterface。如果您使用 TValue.From<IInterface> 放置了TValue,则无法将其转换为不同接口类型的TValue,即使该接口支持该类型。欢迎提交到QC。
使用TValue.From<ITestInterfacedClass>创建TValue确实有效。但是您不能使用简单的SetProperty例程。

TValue.Make(@aRight, RTTIProperty.PropertyType.Handle, Value); RTTIProperty.SetValue(aLeft, Value);TValue.Make(@aRight, RTTIProperty.PropertyType.Handle,Value); RTTIProperty.SetValue(aLeft,Value); - Mielofon

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