J'ai récemment expérimenté intensivement avec les interfaces et le RTTI D2010. Je ne sais pas au moment de l'exécution le type réel de l'interface; bien que j'aurai accès à son nom qualifié en utilisant une chaîne.Diffusion de l'interface Delphi à l'aide de TValue
Considérez ce qui suit:
program rtti_sb_1;
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti, TypInfo, mynamespace in 'mynamespace.pas';
var
ctx: TRttiContext;
InterfaceType: TRttiType;
Method: TRttiMethod;
ActualParentInstance: IParent;
ChildInterfaceValue: TValue;
ParentInterfaceValue: TValue;
begin
ctx := TRttiContext.Create;
// Instantiation
ActualParentInstance := TChild.Create as IParent;
{$define WORKAROUND}
{$ifdef WORKAROUND}
InterfaceType := ctx.GetType(TypeInfo(IParent));
InterfaceType := ctx.GetType(TypeInfo(IChild));
{$endif}
// Fetch interface type
InterfaceType := ctx.FindType('mynamespace.IParent');
// This cast is OK and ChildMethod is executed
(ActualParentInstance as IChild).ChildMethod(100);
// Create a TValue holding the interface
TValue.Make(@ActualParentInstance, InterfaceType.Handle, ParentInterfaceValue);
InterfaceType := ctx.FindType('mynamespace.IChild');
// This cast doesn't work
if ParentInterfaceValue.TryCast(InterfaceType.Handle, ChildInterfaceValue) then begin
Method := InterfaceType.GetMethod('ChildMethod');
if (Method <> nil) then begin
Method.Invoke(ChildInterfaceValue, [100]);
end;
end;
ReadLn;
end.
Le contenu de mynamespace.pas
est la suivante:
{$M+}
IParent = interface
['{2375F59E-D432-4D7D-8D62-768F4225FFD1}']
procedure ParentMethod(const Id: integer);
end;
{$M-}
IChild = interface(IParent)
['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
procedure ChildMethod(const Id: integer);
end;
TParent = class(TInterfacedObject, IParent)
public
procedure ParentMethod(const Id: integer);
end;
TChild = class(TParent, IChild)
public
procedure ChildMethod(const Id: integer);
end;
Pour être complet, la mise en œuvre se déroule comme
procedure TParent.ParentMethod(const Id: integer);
begin
WriteLn('ParentMethod executed. Id is ' + IntToStr(Id));
end;
procedure TChild.ChildMethod(const Id: integer);
begin
WriteLn('ChildMethod executed. Id is ' + IntToStr(Id));
end;
La raison {$define WORKAROUND}
peut être trouvé in this post. Question: est-ce qu'il y a un moyen pour moi de faire le cast de type désiré en utilisant RTTI? En d'autres termes: existe-t-il un moyen pour moi d'invoquer IChild.ChildMethod de savoir 1) le nom qualifié de IChild en tant que chaîne, et 2) une référence à l'instance TChild en tant qu'interface IParent? (Après tout, la distribution codée en dur fonctionne bien, est-ce possible?) Merci!
L'homme, ça a tellement de sens! Je ne pouvais vraiment pas comprendre pourquoi cela ne fonctionnait pas. A la rescousse encore une fois! :) (+1) Je vais le signaler à QC dans la matinée. – conciliator
Le matin est venu plus vite que prévu ... Il est maintenant signalé sous QC# 85339. – conciliator