delphi - Delphi如何检查IInterface的实例是否是IInvokable
问题描述
我想在我的接口实例上做一个包装器,我打算使用 TVirtualInterface 类来做到这一点,但它只接受 IInvokable 实例,有什么办法可以实现 IsInterfaceIInvokable 函数,以便它返回给我,如果过去的实例是否是 IInvokable 实例?
代码:
program InterfaceWrapper;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.TypInfo,
System.Rtti;
type
IMinhaInterface = interface(IInvokable)
['{1DFA8F7B-57BF-44E5-BBBF-76492EE36CEA}']
procedure Fazer;
end;
TMinhaInterfaceImp = class(TInterfacedObject, IMinhaInterface)
public
procedure Fazer;
end;
TWrapper = class(TVirtualInterface)
private
intF: IInterface;
public
constructor Create(const PIID: PTypeInfo; const intF: IInterface);
end;
{ TMinhaInterfaceImp }
procedure TMinhaInterfaceImp.Fazer;
begin
Writeln('procedure TMinhaInterfaceImp.Fazer');
end;
{ TWrapper }
constructor TWrapper.Create(const PIID: PTypeInfo; const intF: IInterface);
begin
inherited Create(PIID);
Self.intF := intF;
Self.OnInvoke := procedure(Method: TRttiMethod; const Args: TArray<TValue>; out Result: TValue)
begin
try
Writeln('Antes');
Result := Method.Invoke(TValue.From(Self.intF), Copy(Args, 1, Length(Args) - 1));
Writeln('Depois');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
end;
end;
function IsInterfaceIInvokable(const intF: IInterface; const PIID: PTypeInfo): Boolean;
begin
Result := intF is IInvokable;
end;
begin
try
var intF := TMinhaInterfaceImp.Create as IMinhaInterface;
if IsInterfaceIInvokable(intF, TypeInfo(IMinhaInterface)) then
begin
intF := TWrapper.Create(TypeInfo(IMinhaInterface), intF) as IMinhaInterface;
end;
intF.Fazer;
var str: string;
Readln(str);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
解决方案
中有未记录的枚举值System.TypInfo.TIntfFlag
(请参阅RSP-24631)
所以你可以使用这个代码——不仅接口继承自,IInvokable
而且如果它有{$M+}
:
function HasMethodInfo(typeInfo: PTypeInfo): Boolean;
type
TIntfFlagEx = (ifHasGuid, ifDispInterface, ifDispatch, ifMethodInfo);
TIntfFlagsEx = set of TIntfFlagEx;
begin
Result := Assigned(typeInfo) and (typeInfo.Kind = tkInterface)
and (ifMethodInfo in TIntfFlagsEx(typeInfo.TypeData.IntfFlags));
end;
推荐阅读
- ruby-on-rails - Dokku:应用程序容器无法启动/找不到服务器“”
- google-cloud-platform - 从 Internet 访问 GKE 内部 LB IP
- php - php/mysql 更新集查询抛出错误
- python-3.x - 在 tkinter 滚动条上显示串行传入数据
- ruby-on-rails - 如何使 Postman 或 Postman Collection Runner 使用 CSV 文件发送 POST 请求,Rails 强参数
- javascript - 如何多次重用相同的代码 - html/css
- python - 如何表示 LSTM 的数据?
- python - sklearn roc_auc_score 的阈值是多少
- quarkus - Can Readiness, Liveness check 通过配置激活/不激活
- javascript - 需要获取mongodb上复杂数据的平均值