How to determine if a descendant of IInterface has a property?

I have many interfaces as a result of importing a type library. So the interfaces look like this:

  ISomeCollection = dispinterface
    ['{6592E851-3D65-4D04-B5F3-B137667B816A}']
    procedure Remove(Identifier: OleVariant); dispid 2;
    function Add(Name: OleVariant; DatabaseType_ID: OleVariant): ERSModel; dispid 3;
    property _NewEnum: IUnknown readonly dispid -4;
    property Item[Identifier: OleVariant]: ERSModel readonly dispid 4;
    property _Item[Identifier: OleVariant]: ERSModel readonly dispid 0; default;
    property Count: Integer readonly dispid 1;
  end;

_NewEnum- This is an idiom for using a Visual Basic loop expression for-each(it's exactly like Delphi for-in) a COM collection of objects - despite the IUnknown declaration, it is really an interface IEnumVARIANT. Since this is the only way to list the elements of the collection, I went around it with:

{This class have just this class function} 
class function TVariantUtils.GetAs<T>(pModeloOleVar: OleVariant): T;
begin
  Result := (T(IUnknown(pModeloOleVar)));
end;

Using:

var 
  EnumColecction: IEnumVariant;
  // TEnumeratorObjects: This is a generic class to implement an enumerator over
  // an IEnumVARIANT interface
  ListOfSubObjects: TEnumaretorObjects; 
begin
  ...
  EnumCollection := TVariantUtils.GetAs<IEnumVariant>(Object.SomeCollection._NewEnum);
  ListOfSubObects := TEnumeratorObjects<ItemofSomeCollection>.Create(EnumCollection);
  ...
End;

The constructor receives the IEnumVariant parameter. I want to create a constructor that gets an IInterface and determines if the ISomeCollection has the _NewEnum IUnknown property - and execute the above code once. I do not know the name or GUID of the interface at compile time.

: delphi-xe , , Delphi XE ( Starter Edition ). D2010.

EDIT: RTTI ( , ):

constructor TEnumeratorVariant<T>.Create(pEnumeraVariante: IInterface);
var
  EnumVar: IEnumVariant;
  Contexto: TRttiContext;
  InfoTipo: TRttiType ;
  PropInfo: TRttiProperty;
  pTipo: PTypeInfo;
begin
  Contexto.Create;
  pTipo := TypeInfo(pEnumeraVariante);
  InfoTipo := Contexto.GetType(TypInfo(pEnumeraVariante));
  PropInfo := InfoTipo.GetProperty('_NewEnum');
  if Assigned(PropInfo) then
  begin
    Supports(PropInfo.GetValue(pEnumeraVariante), IEnumVariant, EnumVar);
    Create(EnumVar);
  end;
  Contexto.Free;
  PropInfo.Free;
  InfoTipo.Free;
end;
+3
2

IDispatch ( , ):

function GetEnumerator(const Disp: IDispatch): IEnumVariant;
var
  DispParams: TDispParams;
  ExcepInfo: TExcepInfo;
  Status: Integer;
  VarResult: OleVariant;
begin
  Result := nil;
  FillChar(DispParams, SizeOf(DispParams), 0);
  FillChar(ExcepInfo, SizeOf(ExcepInfo), 0);
  Status := Disp.Invoke(DISPID_NEWENUM, GUID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, DispParams, @VarResult, @ExcepInfo, nil);
  if Succeeded(Status) then
    Result := IUnknown(VarResult) as IEnumVariant
  else
    DispatchInvokeError(Status, ExcepInfo);
end;
+3

. Delphi RTTI , RTTI . ; . {$M+} , .

+3

All Articles