views:

113

answers:

2

In this code:

TTest<IntfT: IInterface> = class
protected
  fObj : TInterfacedObject;
public
  function  GetVal: IntfT;
end;

How would I implement the GetVal function if I want it to return fObj as an IntfT?

I've tried:

result := fObj as IntfT;

and

fObj.QueryInterface(IntfT,result);

and

result := fObj as IInterface;

but nothing seems to work. This seems like such a simple thing, I keep thinking I must be missing something.

Any ideas?

EDIT

What looks the most promising to me right now is QueryInterface. Currently the compiler complains that IntfT isn't a GUID and I get the impression that if I had the appropriate GUID everything would be happy. Anyone know of a way to get the IID from an interface type that would work in this situation?

+2  A: 

result := fObj as IntfT; ought to work, but apparently the compiler doesn't quite understand interfaces as generics. You should report this in QC.

fObj.QueryInterface(IntfT,result); doesn't work because QueryInterface is a protected member of TInterfacedObject. Also, QueryInterface works by calling GetInterface, which looks for a GUID, and GUIDs and generics don't mix all that well.

result := fObj as IInterface; does compile right for me. What problem are you having with it?

Mason Wheeler
Well, son of a.... yes, it does work. In my actual code I was typecasting from an Items[] property, which should have been of an interface supporting type, but for some reason, with the generics, it didn't recognize that. Bug if I explicitly typecast my Items object to the interface supporting type, suddenly it works. Thanks.
TrespassersW
Hmmmm... at a closer look, "result := fObj as IInterface" doesn't seem to work so well after all. It just delays the compiler error until later. When you actually attempt to use GetVal as the appropriate type, I get a compiler error saying "Incompatible types: 'ISomething' and 'IInterface'"
TrespassersW
+2  A: 

Here is the solution I came up with:

function TTest<IntfT>.GetVal: IntfT;
begin
  fObj.QueryInterface(GetTypeData(TypeInfo(T)).Guid,result);
end;

And that seems to work. (BTW, it works because fObj isn't really a TInterfacedObject, but a different interface implementing class that has a public QueryInterface method).

TrespassersW
Nice! But even with TInterfacedObject, you could use this:(FObj as IInterface).QueryInterface(GetTypeData(TypeInfo(IntfT)).Guid, Result);
TOndrej