Delphi 2010 RTTI 和接口字段

发布于 2024-09-18 07:40:09 字数 2522 浏览 3 评论 0原文

我对 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.

我必须写一个类似的 intf1.B:=intf3; 或者 obj1.B = intf3;

使用 RTTI。

这可能吗?

UPD 这是工作:

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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许你一世情深 2024-09-25 07:40:09

不幸的是,这不起作用,因为 RTTI.pas 中的接口转换代码不会调用 QueryInterface。如果将 TValue 与 TValue.From 一起放入,则无法将其转换为不同接口类型的 TValue,即使该接口支持该类型也是如此。请随意将其提交给 QC。

不过,使用 TValue.From 创建 TValue 确实有效。但是这样您就不能使用简单的 SetProperty 例程。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文