Delphi t引用包中的字典强制转换失败

Delphi t引用包中的字典强制转换失败,delphi,delphi-xe2,Delphi,Delphi Xe2,一个t字典被分配给一个TObject变量。我可以将TOBject转换回同一项目中的t词典。但是,如果在引用的bpl项目中执行强制转换,则强制转换将失败,具体取决于项目的引用方式 测试代码: procedure TestTDefault.Test1; var Obj: TObject; begin Obj := TDictionary<string, Integer>.Create; Check(Obj is TDictionary<string, Integer&g

一个t字典被分配给一个TObject变量。我可以将TOBject转换回同一项目中的t词典。但是,如果在引用的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;
过程TestTDefault.Test1;
变量
对象:对象;
开始
Obj:=TDictionary.Create;
检查(Obj是t字典);
CheckNotNull(Obj作为TDictionary);
//这将调用引用的bpl包中的函数。
//如果Obj可以转换回TDictionary,则返回True。
CheckTrue(TestIfDictionary(Obj));//结果取决于引用的包是否包含在
结束;
依赖包中的函数:

function TestIfDictionary(aObject: TObject): Boolean;
begin
  Result := aObject is TDictionary<string,Integer>;
end;
函数TestIfDictionary(aoobject:TObject):布尔;
开始
结果:=a对象是t字典;
结束;
我有一个简单的项目组,只有两个包:

  • DUnit测试运行程序(Package1Tests.exe)
  • Package1.bpl
  • 两个包都有相同的编译器/链接器选项集

    非常奇怪的是,只有当Package1未作为运行时包列出时,测试才会工作:

    但是,如果Package1被列为运行时包,测试将失败!!

    我使用的是XE2。至于目的,这个问题在处理RTTI时出现。我能够在这个简单的测试项目中隔离问题。问题与RTTI无关。 需要注意的是,如果我使用TStringList而不是TDictionary,那么测试总是有效的。所以这个问题似乎和泛型有关。 如果需要,我可以提供简单的测试项目


    我花了相当长的时间研究这个问题。我很高兴能发现是什么引发了这个问题。但不幸的是,我无法理解为什么会发生这种情况。

    您应该为这个泛型类使用类型声明

    type
     Tx = TDictionary<string, Integer>;
    

    RTTI在您的情况下并不重要。

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

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

    type
      TDictionaryStringInteger = class(TDictionary<string, Integer>);
    
    类型
    TDictionaryStringInteger=类(TDictionary);
    
    然后使用
    TDictionaryStringInteger
    代替
    TDictionary
    。然而,这几乎会削弱您的代码,因为它会阻止您编写使用泛型类型的泛型方法


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

    不幸的是,这不起作用。如果我使用Tx=TStringList或TInterfaceList,它可以工作。如果我们所选的班级是非泛型的,这似乎总是有效的。@santiagoIT是对的。您需要创建新类型,而不是别名
    Tx=class(TDictionary)
    可以做到这一点,但这在长期运行中几乎没有用处!我现在明白了。来自.NET的Delphi泛型确实很难处理所有的限制和限制。与.net相比,delphi中的泛型太差了。真的很可悲:-(
    type
      TDictionaryStringInteger = class(TDictionary<string, Integer>);