Delphi:RTTI和TObjectList <tobject> </tobject>

时间:2010-04-01 08:26:02

标签: delphi generics delphi-2010 rtti

根据之前post的一个答案,我正在调查以下设计的可能性

TChildClass = class(TObject)
private
  FField1:  string;
  FField2:  string;
end;

TMyClass = class(TObject)
private
  FField1:  TChildClass;
  FField2:  TObjectList<TChildClass>;
end;

现在,在现实世界中,TMyClass将有10个不同的列表,所以我希望能够使用RTTI解决这些列表。但是,我对这个类的其他字段不感兴趣,所以我需要检查某个字段是否是某种TObjectList。这是我到目前为止所得到的:

procedure InitializeClass(RContext: TRttiContext; AObject: TObject);
var
  ROwnerType:   TRttiType;
  RObjListType: TRttiType;
  RField:       TRttiField;
  SchInf:       TSchemaInfoDetail;
begin
ROwnerType := RContext.GetType(AObject.ClassInfo);
RObjListType := RContext.GetType(TObjectList<TObject>);
for RField in ROwnerType.GetFields do begin
  // How do I check if the type of TMyClass.FField2 (which is TObjectList<TChildClass>) is some sort of TObjectList?
end;

显然,RField.FieldType <> RObjListType.FieldType。但是,他们确实有一些关系,不是吗?对于常见功能进行非常精细的检查似乎很可怕(而且错误!),以使RField.FieldType很可能实际上是TObjectList

老实说,我对仿制药感到非常不舒服,所以这个问题可能很天真。但是,我非常乐意学习。以上解决方案是否可以实施? TIA!

2 个答案:

答案 0 :(得分:6)

每个通用实例化都是唯一的,与RTTI相关的其他实例化没有任何关系。因为Delphi无法在运行时实例化泛型类型,所以没有相同的例子。 .NET的GetGenericTypeDefinition。你能做的最好的就是看看这种类型的形状 - 例如是否实施GetEnumeratorAdd等。

这也可以足够灵活地处理常规集合类型,而不仅仅是从TObjectList<T>实例化的集合类型。 C#与其集合初始化器类似 - 它查找Add方法并插入对它的调用:

http://msdn.microsoft.com/en-us/library/bb384062.aspx

答案 1 :(得分:2)

Delphi可以在运行时实例化泛型类型。 问题是,泛型类型通常不包含在运行时信息中。如果您持有特定类型的全局变量(在您的情况下为TObjectList&lt; TChildClass&gt;),则在初始化部分中实例化(并释放)该特定类的运行时信息将不会被链接器剥离,您将能够实例化它以后动态。 (您需要为context.findType()提供类的完全限定名称才能正常工作。) 我花了一些时间搞清楚如何做到这一点,我对此肯定不满意,但因为我还没有找到另一种方法,我现在必须处理它。如果有人知道更好的方法让我知道。