【问题标题】:Delphi: RTTI and TObjectList<TObject>Delphi:RTTI 和 TObjectList<TObject>
【发布时间】:2010-04-01 08:26:02
【问题描述】:

基于对较早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 &lt;&gt; RObjListType.FieldType。但是,他们确实有一些关系,不是吗?为了使RField.FieldType很可能实际上是TObjectList而对通用功能进行非常精细的检查似乎很可怕(而且是错误的!)。

说实话,我对泛型感到很不舒服,所以这个问题可能很幼稚。但是,我很乐意学习。上述解决方案是否可以实施?蒂亚!

【问题讨论】:

  • 谢谢梅森。我猜,将其标记为 2010 年的问题有点矫枉过正。

标签: delphi generics delphi-2010 rtti


【解决方案1】:

每个通用实例化都是唯一的,并且在 RTTI 方面与其他实例化无关。因为 Delphi 不能在运行时实例化泛型类型,所以没有等价于例如.NET 的GetGenericTypeDefinition。你能做的最好的就是看类型的形状——例如。是否实现了GetEnumeratorAdd等?

这也可以足够灵活地处理一般集合类型,而不仅仅是从TObjectList&lt;T&gt; 实例化的集合类型。 C# 对其集合初始化器做了类似的事情 - 它查找 Add 方法并插入对它的调用:

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

【讨论】:

  • 谢谢巴里!我想我会按照您的指示寻找 Add-method。 +1 :)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 2013-03-08
    相关资源
    最近更新 更多