我有两个类层次结构:
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
但我需要对所有列表进行常规检查。
请给我指路。有可能吗?
答案 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
检查。