I'm storing small interfaces from a range of objects into a single TInterfaceList 'store' with the intention of offering list of specific interface types to the end user, so each interface will expose a 'GetName' function but all other methods are unique to that interface type. For example here are two interfaces:
IBase = interface
//----------------------------------------
function GetName : string;
//----------------------------------------
end;
IMeasureTemperature = interface(IBase)
//------------------------------------
function MeasureTemperature : double;
//----------------------------------------
end;
IMeasureHumidity = interface(IBase)
//----------------------------------------
function MeasureHumidity: double;
//----------------------------------------
end;
I put several of these interfaces into a single TInterfaceList and then I'd like to scan the list for a specific interface type (e.g. 'IMeasureTemperature') building another list of pointers to the objects exporting those interfaces. I wish to make no assumptions about the locations of those objects, some may export more than one type of interface. I know I could do this with a class hierarchy using something like:
If FList[I] is TMeasureTemperature then ..
but I'd like to do something simliar with an interface type, Is this possible?
Just use Supports, like this:
var
oMTIntf: IMeasureTemperature;
...
If Supports(FList[I], IMeasureTemperature, oMTIntf) then ..
I guess that might satisfy your needs.
function InterfaceRefIsInterface(Intf : IUnknown; ExpectedIntf : TGUID) : Boolean;
var vReference : IUnknown;
begin
if Supports(Intf, ExpectedIntf, vReference) then
Result := Intf = vReference
else
Result := False;
end;
I'm not sure how the function will behave when Intf and ExpectedIntf inherits from one another, but this will return TRUE in the case Intf is an exact match of ExpectedIntf.
In your exemple, IMeasureHumidity won't return true on IMeasureTemperature, but I'm not sure how it will react to IBase. According to preliminary testing, it will also return FALSE on IBase.
You may use the Supports
function in SysUtils, they are pretty safe (unless you try them on unitialized memory) and you only need a target variable of the exact interface type you try to cast to:
procedure DoSomethingInList(AList: IInterfaceList;);
var
i: Integer;
liItem: IInterface;
liMeasureTemp: IMeasureTemperature;
liMeasureHumi: IMeasureHumidity;
begin
AList.Lock;
try
for i := 0 to AList.Count - 1 do
begin
liItem := AList[i];
if Supports(liItem, IMeasureTemperature, liMeasureTemp) then
//... liMeasureTemp.MeasureTemperature ...
else if Supports(liItem, IMeasureHumidity, liMeasureHumi) then
//... liMeasureHumi.MeasureHumidity ...
else
//...
end;
finally
AList.Unlock;
end;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With