2010-09-03 26 views
6

J'ai un problème avec les propriétés du type IInterface. Je ne sais pas comment attribuer des valeurs à ces propriétés à l'aide RTTIDelphi 2010 Champs RTTI et Interface

Voici un exemple :.

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. 

j'écrire un analogue de intf1.B: = intf3; ou obj1.B = intf3;

en utilisant RTTI.

Est-ce possible?

UPD Il est le travail:

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; 
+0

RTTIProperty.SetValue (lagauche, TValue.From (aright comme ITestInterfacedClass)); c'est du travail, mais dans SetProperty je ne veux rien de la noblesse de ITestInterfacedClass. – Mielofon

Répondre

2

Malheureusement, cela ne fonctionne pas parce que le code de conversion d'interface en RTTI.pas ne remet pas QueryInterface. Si vous définissez une valeur TValue avec TValue.From<IInterface>, vous ne pouvez pas la convertir en TValue d'un type d'interface différent, même si l'interface prend en charge ce type. N'hésitez pas à soumettre cela au QC.

Création du TValue avec TValue.From<ITestInterfacedClass> fonctionne, cependant. Mais vous ne pouvez pas utiliser la routine SetProperty simple.

+0

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