TDictionary被分配给TObject变量。我可以将TOBject投射回同一项目中的TDictionary。但是,如果在引用的bpl项目中完成了转换,则转换将失败,具体取决于如何引用该项目。

测试代码:

procedure TestTDefault.Test1;
var
  Obj: TObject;
begin
  Obj := TDictionary<string, Integer>.Create;
  Check(Obj is TDictionary<string, Integer>);
  CheckNotNull(Obj as TDictionary<string, Integer>);

  // this calls the function in the referenced bpl package.
  // Returns True if Obj can be cast back to a TDictionary.
  CheckTrue(TestIfDictionary(Obj)); // outcome depends if referenced packge is included in <DCC_UsePackage>
end;


依赖包中的函数:

function TestIfDictionary(aObject: TObject): Boolean;
begin
  Result := aObject is TDictionary<string,Integer>;
end;


我有一个只有两个软件包的简单项目组:


DUnit测试运行器(Package1Tests.exe)
包1.bpl




两个软件包都有相同的编译器/链接器选项集。

十分奇怪的是,仅当Package1未列为运行时程序包时,该测试才有效:


但是,如果Package1被列出为运行时程序包,则测试失败!


我正在使用XE2。至于目的,在处理RTTI时会出现此问题。我能够在这个简单的Test项目中找出问题所在。问题与RTTI无关。
请注意,如果我不是使用TDictionary,而是使用TStringList,则测试始终有效。因此,问题似乎与泛型有关。
如果需要,我可以提供简单的测试项目。

我花了很多时间来解决这个问题。我很高兴发现导致问题的原因。但不幸的是,我无法理解为什么会这样。

最佳答案

您在这里遇到的问题与通用实例化有关。每个模块分别实例化泛型,因此它们具有不同的类型标识。这是泛型设计及其与运行时程序包交互的基本限制。

您可以在包中的一个单元中实例化泛型类型,例如:

type
  TDictionaryStringInteger = class(TDictionary<string, Integer>);


然后使用TDictionaryStringInteger代替TDictionary<string, Integer>。但是,这几乎会使您的代码瘫痪,因为它使您停止编写使用泛型类型的泛型方法。

摆脱绑定的另一种方法是停止使用运行时包。坦白说,这对我来说似乎更具吸引力。

10-08 15:53