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: TTestInt开发者_JAVA技巧erfacedClass;
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.
精彩评论