delphi - 使用 Rtti 设置方法字段

标签 delphi annotations delphi-xe rtti

我正在使用 Delphi XE 编写一个基类,这将允许降级类通过应用注释来映射 dll 方法。但是,我收到类型转换错误,这是可以理解的。

本质上,基类应该是这样的:

TWrapperBase = class
public
  FLibHandle: THandle;
  procedure MapMethods;
end;

procedure TWrapperBase.MapMethods;
var
  MyField: TRttiField;
  MyAttribute: TCustomAttribute;
  pMethod: pointer;
begin
  FLibHandle := LoadLibrary(PWideChar(aMCLMCR_dll));
  for MyField in TRttiContext.Create.GetType(ClassType).GetFields do
    for MyAttribute in MyField.GetAttributes do
      if MyAttribute.InheritsFrom(TMyMapperAttribute) then
      begin
        pMethod := GetProcAddress(FLibHandle, (MyAttribute as TMyMapperAttribute).TargetMethod);
        if Assigned(pMethod) then
          MyField.SetValue(Self, pMethod); // I get a Typecast error here
end;

降级类可能如下所示:

TDecendant = class(TWrapperBase)
private type
  TSomeDLLMethod = procedure(aParam: TSomeType); cdecl;
private
  [TMyMapperAttribute('MyDllMethodName')]
  FSomeDLLMethod: TSomeDLLMethod;
public
  property SomeDLLMethod: TSomeDLLMethod read FSomeDLLMethod;
end;

我可以通过在覆盖的“MapMethods”中对每个方法的链接进行硬编码来以不同的方式实现它。然而,这将要求每个后代都这样做,我想避免这样做。

我知道在这种情况下使用的 TValue 将包含一个指针,但类型不正确(procedure(aParam: TSomeType); cdecl; 在这种情况下).

我的问题:有没有办法将来自“GetProcAdress”的指针作为正确的类型传递,或者直接设置字段(例如使用字段地址“PByte(Self)+MyField.Offset”,您可以用来设置记录属性的值)?

使用旧的 Rtti,这可以完成,但仅限于已发布的属性并且没有任何类型检查:

if IsPublishedProp(Self, 'SomeDLLMethod') then
  SetMethodProp(Self, 'SomeDLLMethod', GetProcAddress(FLibHandle, 'MethodName');

最佳答案

有两个问题:

首先,您的 EInvalidCast 是由于 TValue 对类型转换非常严格造成的。您正在传递一个 Pointer 并希望设置一个类型为 TSomeDLLMethod 的字段。您需要显式传递具有正确类型信息的 TValue

if Assigned(pMethod) then
begin
  TValue.Make(@pMethod, MyField.FieldType.Handle, value);
  MyField.SetValue(Self, value);
 end;

现在您将遇到另一个 EInvalidCast 异常,该异常是由于 XE 中 Rtti.pas 的 GetInlineSize 方法中的错误而触发的,该方法为 tkProcedure 类型返回 0的类型。我不知道这个问题在哪个版本中得到修复,但它在 XE5 中不再存在。

对于 XE,这可以通过使用我不久前写的一个单元来修复(我刚刚更新以修复这个错误):RttiPatch.pas .

我还报告了原始问题,因为 Pointer 与过程类型兼容,因此 TValue 也应该处理这个问题:http://qc.embarcadero.com/wc/qcmain.aspx?d=124010

关于delphi - 使用 Rtti 设置方法字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23013489/

相关文章:

java - 关于方法上的 Spring @Transactional 注释的一些说明

delphi - 如何在 Delphi XE 中检查连接.onion 域 Tor URL?

delphi - POST 响应的 TIdHTTP 字符编码

delphi - 在 Delphi 中使用通配符搜索字符串中的模式?

delphi - FindComponent 甚至会找到声明为私有(private)的东西吗?

delphi - Font.Charset和TButton

delphi - 如何在DWScript中公开记录的动态数组?

Java:允许带有自定义注释的对象的集合

windows - 关于 JvPatchFile 组件?

iphone - 为 MapKit 注释将 HTML 转换为纯文本