TDictionary强制转换在引用的包中失败

时间:2015-05-12 14:38:19

标签: delphi delphi-xe2

将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;

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

  1. DUnit Test Runner(Package1Tests.exe)
  2. Package1.bpl
  3. Project Group

    两个软件包都设置了相同的编译器/链接器选项。

    奇怪的是,只有当Package1未被列为运行时包时,测试才有效: Correct

    但是,如果Package1被列为运行时包,则测试失败!! enter image description here

    我正在使用XE2。至于目的,这个问题在处理RTTI时浮出水面。我能够在这个简单的测试项目中找出问题所在。问题与RTTI无关。 就像一个注释,如果不是使用TDictionary我使用TStringList,那么测试总是有效。所以问题似乎与泛型有某种关系。 如果需要,我可以提供简单的测试项目。

    我花了很长时间来追查这个问题。我很高兴我发现了触发问题的原因。但不幸的是,我可能只是不明白为什么会这样。

2 个答案:

答案 0 :(得分:1)

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

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

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

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

绑定的另一种方法是停止使用运行时包。坦率地说,这似乎对我更有吸引力。

答案 1 :(得分:0)

您应该为此通用类使用类型声明。

type
 Tx = TDictionary<string, Integer>;

...

Obj := Tx.Create;
Check(Obj is Tx);

RTTI与您的情况无关。