我目前正在考虑一种情况,我想要一个在其项目 IF 上调用Free
的泛型类,这些类是对象类型。所以我尝试了以下内容:
if (PTypeInfo (TypeInfo (T)).Kind = tkClass) then
begin
RttiType := RttiContext.GetType (TypeInfo (T));
FreeMethod := RttiType.GetMethod ('Free');
if (FreeMethod <> nil) then
FreeMethod.Invoke (FInstance, []);
end;
不幸的是最后一行没有编译,这并不奇怪,因为类型不匹配。问题是:我可以编译吗?我尝试转换为Pointer
然后转到TObject
,但这给了我一个无效的类型转换错误。有没有办法让FInstance : T
加入TObject
引用,然后我可以传递给Invoke
?
或者还有其他方法可以达到我的目的吗?请注意,重点是获取此类中的所有内容,因此我不想创建只接受对象的TObjectMyClass
。
感谢您的帮助。
答案 0 :(得分:5)
这不够吗?
if PTypeInfo(TypeInfo(T))^.Kind = tkClass then
TObject(FInstance).Free;
答案 1 :(得分:2)
直接转换为TObject似乎在Delphi 2010中有效:
FreeMethod.Invoke (TObject(FInstance), []);
完整示例:
implementation
uses TypInfo, Rtti;
{$R *.dfm}
type
TTest<T> = class
FInstance : T;
procedure F;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
O : TTest<TObject>;
begin
O := TTest<TObject>.Create;
O.FInstance := TStringList.Create;
O.F;
O.Free;
end;
{ TTest<T> }
procedure TTest<T>.F;
var
RttiType : TRttiType;
FreeMethod : TRttiMethod;
RttiContext : TRttiContext;
begin
if (PTypeInfo (TypeInfo (T)).Kind = tkClass) then
begin
RttiType := RttiContext.GetType (TypeInfo (T));
FreeMethod := RttiType.GetMethod ('Free');
if (FreeMethod <> nil) then
FreeMethod.Invoke (TObject(FInstance), []);
end;
end;
答案 2 :(得分:2)
这给我带来了糟糕的设计。泛型的一个要点是摆脱像这样的动态类型决策。
如果你真的在使用泛型特性,那么让我更有意义的是让一个受限制的类型参数的子类只占用TObject
个后代。由于您必须静态地决定如何实例化泛型类,因此当TMyObjectClass
是一个类时使用T
并在其他地方使用TMyClass
毫无疑问。
如果单个容器需要同时包含对象和非对象,我猜你会被迫采取你正在采取的方法。但如果情况并非如此,那么我觉得有点不对劲。
答案 3 :(得分:1)
实际上,我自己就找到了答案。 TValue.From
可以解决问题:
if (PTypeInfo (TypeInfo (T)).Kind = tkClass) then
begin
RttiType := RttiContext.GetType (TypeInfo (T));
FreeMethod := RttiType.GetMethod ('Free');
if (FreeMethod <> nil) then
FreeMethod.Invoke (TValue.From <T> (FInstance), []);
end;