TDictionary failure in referenced package

A TDictionary is assigned to the TObject variable. I can include the TOB object back to TDictionary in the same project. However, if the cast is done in a referenced bpl project, the translation is done depending on how the project is referenced.

Security Code:

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 in dependent package:

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

      

I have a simple group of projects with two packages:

  • DUnit Test Tester (Package1Tests.exe)
  • Package1.bpl

Project Group

Both packages have the same compiler / linker options.

What's very strange is that the test only works if Package1 is not listed as a runtime package: Correct

However, the test fails if the runtime package is specified in Package1! enter image description here

I am using XE2. As far as the goal is concerned, this issue came up when working with RTTI. I was able to isolate the problem in this simple test project. The problem has nothing to do with RTTI. As a side note, if I use TStringList instead of using TDictionary, then the test always works. So the problem seems to be with generics. I can make a simple test project available if needed.

I've spent quite a lot of time fixing this issue. I'm glad I was able to figure out what is causing the problem. But unfortunately I just can't figure out why this is happening.

+3


source to share


2 answers


The problem you are having here is with a typical instance. Each module separately instantiates a generic type and therefore has a different type. This is a major limitation of generics design and how it interacts with runtime packages.

You can instantiate a type type in a module in a package, for example:

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

      



And then use TDictionaryStringInteger

instead TDictionary<string, Integer>

. However, this pretty much distorts your code as it prevents you from writing generic methods that use generic types.

Another way out of your binding is to stop using runtime packages. To be honest, it seems more attractive to me.

+1


source


You must use a type declaration for this generic class.

type
 Tx = TDictionary<string, Integer>;

      

....



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

      

RTTI doesn't matter in your case.

0


source







All Articles