У меня много интерфейсов в результате импорта библиотеки типов. Итак, интерфейсы такие:
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
- это идиома для потребления операторов цикла Visual Basic for-each
(точно так же, как Delphi for-in
) коллекции COM-объектов - несмотря на объявление IUnknown, это действительно IEnumVARIANT
интерфейс. Так как это единственный способ перечислить элементы коллекции, я обошел это с помощью:
{This class have just this class function}
class function TVariantUtils.GetAs<T>(pModeloOleVar: OleVariant): T;
begin
Result := (T(IUnknown(pModeloOleVar)));
end;
Использование:
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;
Конструктор получает параметр IEnumVariant. Что я хочу, это создать конструктор
которые получают IInterface и определяют, имеет ли ISomeCollection свойство _NewEnum
IUnknown type - и сделайте приведенный выше код один раз.
Я не знаю ни имени, ни GUID интерфейса во время компиляции.
Obs: тег delphi-xe потому что я хочу знать механизм, даже если он работает только на Delphi XE
(даже если мне нужно купить версию для начинающих только для этого).
Я использую 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;