将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;
我有一个只包含两个包的简单项目组:
两个软件包都设置了相同的编译器/链接器选项。
奇怪的是,只有当Package1未被列为运行时包时,测试才有效:
但是,如果Package1被列为运行时包,则测试失败!!
我正在使用XE2。至于目的,这个问题在处理RTTI时浮出水面。我能够在这个简单的测试项目中找出问题所在。问题与RTTI无关。 就像一个注释,如果不是使用TDictionary我使用TStringList,那么测试总是有效。所以问题似乎与泛型有某种关系。 如果需要,我可以提供简单的测试项目。
我花了很长时间来追查这个问题。我很高兴我发现了触发问题的原因。但不幸的是,我可能只是不明白为什么会这样。
答案 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与您的情况无关。