如何使用继承的parameter_检查泛型中的继承

时间:2014-07-27 10:59:37

标签: delphi generics

我有两个类层次结构:

1

TObject
  --TAmObject
    --TAmField
    --TAmFarm

2

TObjectList<T: TAmObject>
  --TAmObjectList<T: TAmObject>
     --TAmFieldList
     --TAmFarmList

我有一些链接到TTreeView节点的对象。

然后我有一个任务要检查:

if TObject(node.Data) is TAmObject

if TObject(node.Data) is TAmObjectList<TAmObject>

首先检查是好的,并没有给我带来任何问题。 第二个我遇到了一些困难。

请告诉我检查的方法。 例如,我将TamFarmList链接到节点。

然后编译说我:

TObject(node.Data) is TAmObjectList<TAmObject> = FALSE

TObject(node.Data) is TAmObjectList<TAmFarm> = TRUE

但我需要对所有列表进行常规检查。

请给我指路。有可能吗?

1 个答案:

答案 0 :(得分:2)

这是Delphi不支持的协方差问题。由于泛型类型不提供其类型参数的反映,因此您必须找到其他方法。

我过去使用的一个解决方案是对类型名称进行一些字符串解析,然后使用RTTI来执行C#反射所能做的事情。它并不完美,但过去做得很好。

以下是一些使用Spring4D的示例代码。

uses
  Spring.Helpers,
  Spring.Reflection;

...

var
  t: TRttiType;
begin
  t := TType.GetType(TObject(node.Data).ClassType);
  if (t.GetGenericTypeDefinition = 'TAmObjectList<>')
    and (t.GetGenericArguments[0].AsInstance.MetaclassType.InheritsFrom(TAmObject)) then

如果您的实例直接是TAmObjectList<T>,其中T为TAmObject,则此方法有效。如果您希望它适用于后代列表类,则必须在实例上执行继承层次结构,并对其执行GetGenericTypeDefinition检查。