Delphi Rtti para interfaces en un contexto genérico
para un marco escribí un contenedor que toma cualquier objeto, interfaz o tipo de registro para explorar sus propiedades o campos. La declaración de clase es la siguiente:
TWrapper<T> = class
private
FType : TRttiType;
FInstance : Pointer;
{...}
public
constructor Create (var Data : T);
end;
En el constructor, trato de obtener la información de tipo para otros pasos de procesamiento.
constructor TWrapper<T>.Create (var Data : T);
begin
FType := RttiCtx.GetType (TypeInfo (T));
if FType.TypeKind = tkClass then
FInstance := TObject (Data)
else if FType.TypeKind = tkRecord then
FInstance := @Data
else if FType.TypeKind = tkInterface then
begin
FType := RttiCtx.GetType (TObject (Data).ClassInfo); //<---access violation
FInstance := TObject (Data);
end
else
raise Exception.Create ('Unsupported type');
end;
Me pregunto si esta infracción de acceso es un error en el compilador de Delphi (estoy usando XE). Después de una investigación adicional, escribí una función de prueba simple, que muestra que pedir el nombre de la clase también produce esta excepción:
procedure TestForm.FormShow (Sender : TObject);
var
TestIntf : IInterface;
begin
TestIntf := TInterfacedObject.Create;
OutputDebugString(PChar (TObject (TestIntf).ClassName)); //Output: TInterfacedObject
Test <IInterface> (TestIntf);
end;
procedure TestForm.Test <T> (var Data : T);
begin
OutputDebugString(PChar (TObject (Data).ClassName)); //access violation
end;
¿Puede alguien explicarme, qué está mal? También probé el procedimiento sin un parámetro var que tampoco funcionó. Cuando se utiliza un procedimiento no genérico, todo funciona bien, pero para simplificar el uso del contenedor, la solución genérica sería buena, porque funciona para objetos y graba de la misma manera.
Saludos cordiales
Cristian