导入类型库后,我有很多接口。所以,接口是这样的:
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,但它确实是{ {1}}界面。因为它是枚举集合项目的唯一方法,所以我得到了:
IEnumVARIANT
使用:
{This class have just this class function}
class function TVariantUtils.GetAs<T>(pModeloOleVar: OleVariant): T;
begin
Result := (T(IUnknown(pModeloOleVar)));
end;
构造函数接收IEnumVariant参数。我想要的是创建一个构造函数 接收IInterface并确定ISomeCollection的_NewEnum属性是否为 IUnknown类型 - 并执行上面的代码一次。 我不知道编译时接口的名称或GUID。
Obs:delphi-xe标签是因为我想知道机制,即使只适用于Delphi XE (即使我需要为此购买简化版)。 我用D2010。
修改 我尝试使用RTTI(它编译但不起作用):
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;
答案 0 :(得分:3)
你走在正确的轨道上。 Delphi的RTTI可以找到接口的方法,但接口必须为这些方法生成RTTI。它默认不这样做;你必须启用它。将{$M+}
指令放在类型库导入单元的顶部,它应该可以工作。
答案 1 :(得分:3)
尝试使用标准的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;