Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi:通过RTTI获取/设置属性时未应用方法解析子句_Delphi_Rtti - Fatal编程技术网

Delphi:通过RTTI获取/设置属性时未应用方法解析子句

Delphi:通过RTTI获取/设置属性时未应用方法解析子句,delphi,rtti,Delphi,Rtti,我试图通过对各种接口属性使用方法解析子句,将功能添加到现有代码中 虽然这样做很好,但在代码中获取/设置属性时,在尝试通过RTTI设置或获取属性时失败 使用RTTI时,将调用第一个实现类方法 下面是显示问题的代码: program TestIntfMethodResolutions; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Variants, System.Classes, TypInfo, R

我试图通过对各种接口属性使用方法解析子句,将功能添加到现有代码中

虽然这样做很好,但在代码中获取/设置属性时,在尝试通过RTTI设置或获取属性时失败

使用RTTI时,将调用第一个实现类方法

下面是显示问题的代码:

program TestIntfMethodResolutions;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Variants,
  System.Classes,
  TypInfo,
  RTTI{,
  uRTTIHelper};


type
   ITestInterface = interface
   ['{61553B5F-574A-4B0F-AB6F-0560E324B463}']
    function GetA:integer;
    procedure SetA(const AVal:integer);
    property A:integer read GetA write SetA;
    end;

   {$RTTI EXPLICIT METHODS([vcPrivate,vcPublic])}
   TTintimpl1 = class(TInterfacedObject,ITestInterface)
    private
    FA:integer;
    function GetA: integer;

    procedure SetA(const Value: integer);virtual; // Does not need to be virtual

    public
      property A:integer read GetA write SetA;

    end;

   {$RTTI EXPLICIT METHODS([vcPrivate,vcPublic])}

   //Explicit RTTI settings causes the Private methods to show up in the method list
   TIntimpl2 = class(TTIntimpl1,ITestInterface)
    private
      procedure MySetA(const Value:integer);virtual;

    public
      procedure ITestInterface.SetA = MySetA;

    end;

  TMain = class

  private
    { Private declarations }
  public
    { Public declarations }
    procedure FormCreate;
    end;

var
  Form5: TMain;

procedure TMain.FormCreate;
var
  ctx:TRttiContext;
  avalue,bvalue:tvalue;
  atype,bastyp:TRttiType;
  aproplist:Tarray<TRttiProperty>;
  amethlist:Tarray<TRttiMethod>;
  isinst:boolean;
  aninst:TRttiInstanceType;
  anintf:TRttiInterfaceType;
  intflist:Tarray<TRttiInterfaceType>;
  inst:pointer;
  anint:ITestInterface;
  aprop:TRttiProperty;
  codeptr:pointer;
  asetmeth:TRTTIMethod;

begin
  ctx:=TRttiContext.Create;

  //Faxisloopthr:=TIntimpl2.Create;

  anint:=TIntimpl2.Create;

  avalue:=anint as TObject;
  atype:=ctx.GetType(avalue.TypeInfo);

  if atype.IsInstance then
    begin
      aninst:=atype.AsInstance;
      aproplist:=aninst.GetProperties;
      amethlist:=aninst.GetMethods;

      bvalue:=TValue.FromOrdinal(aproplist[0].PropertyType.Handle,1);
      inst:=avalue.AsObject;
      aprop:=aproplist[0]; //I could have called aproplist[0].SetValue(...
      aprop.SetValue(inst,bvalue);
      end;

  writeln('RTTI result '+anint.A.ToString); //Should give me 20 but I get 10 everytime


  //asetmeth:=aprop.SetterMethod(inst); // returns SetA and not MySetA - need uRTTIhelper unit. https://github.com/RRUZ/blog/tree/master/RTTI

//      setpropvalue(inst,aprop.PropInfo,bvalue.AsVariant); // calls SetA and not MySetA

  //Manually setting the value calls the correct method

  anint.A:=1;
  writeln('Direct setting '+anint.A.ToString);

  end;


{ T2ndIntf }


{ TTintimpl1 }

function TTintimpl1.GetA: integer;
begin
  Result:=FA;
  end;

procedure TTintimpl1.SetA(const Value: integer);
var
  a:integer;
begin
  FA:=Value*10;
  writeln('In SetA ',FA);
  end;

{ TIntimpl2 }


//Should get called - but the 1st implementing parent gets called
procedure TIntimpl2.MySetA(const Value: integer);

begin
  FA:=Value*20;
  writeln('In MySetA ',FA);
  end;

begin
  Form5:=TMain.Create;
  try
    Form5.FormCreate;
  finally
    Form5.Free;
    readln;
    end;

  end.
程序测试分辨率;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils,
系统变量,
系统,班级,,
TypInfo,
RTTI{,
uRTTIHelper};
类型
ITestInterface=接口
[{61553B5F-574A-4B0F-AB6F-0560E324B463}]
函数GetA:integer;
过程SetA(常数AVal:整数);
属性A:整数读取GetA写入SetA;
结束;
{$RTTI显式方法([vcPrivate,vcPublic])}
TTintimpl1=类(TInterfacedObject,ITestInterface)
私有的
FA:整数;
函数GetA:integer;
程序SetA(常量值:整数);虚拟的;//不需要是虚拟的
公众的
属性A:整数读取GetA写入SetA;
结束;
{$RTTI显式方法([vcPrivate,vcPublic])}
//显式RTTI设置会导致私有方法显示在方法列表中
TIntimpl2=类(TTIntimpl1,ITestInterface)
私有的
过程MySetA(常量值:整数);事实上的
公众的
程序ITestInterface.SetA=MySetA;
结束;
TMain=类
私有的
{私有声明}
公众的
{公开声明}
程序表单创建;
结束;
变量
表5:TMain;
程序TMain.FormCreate;
变量
ctx:trtti上下文;
avalue,bvalue:tvalue;
atype,bastyp:trttype;
停机坪医师:柏油;
名单:焦油;
isinst:布尔型;
列表:trttInstanceType;
anintf:trtti接口类型;
intflist:Tarray;
仪器:指针;
提示:ITestInterface;
aprop:trtti属性;
编码器:指针;
asetmeth:trtti法;
开始
ctx:=TRttiContext.Create;
//Faxisloopthr:=tintinimpl2.Create;
anint:=2.Create;
avalue:=作为对象的信息;
atype:=ctx.GetType(avalue.TypeInfo);
如果atype.IsInstance,则
开始
Anist:=atype.AsInstance;
aproplist:=一个st.GetProperties;
amethlist:=anist.GetMethods;
bvalue:=TValue.FromOrdinal(aproplist[0]。PropertyType.Handle,1);
inst:=avalue.AsObject;
aprop:=aproplist[0]//我本可以调用aproplist[0]。SetValue(。。。
近似设定值(仪表、B值);
结束;
writeln('RTTI result'+anint.A.ToString);//应该给我20,但每次我都得到10
//asetmeth:=aprop.SetterMethod(inst);//返回SetA而不是MySetA-需要uRTTIhelper单元。https://github.com/RRUZ/blog/tree/master/RTTI
//setpropvalue(inst,aprop.PropInfo,bvalue.AsVariant);//调用SetA而不是MySetA
//手动设置该值将调用正确的方法
A:=1;
writeln(‘直接设置’+int.A.ToString);
结束;
{T2ndIntf}
{TTintimpl1}
函数TTintimpl1.GetA:integer;
开始
结果:=FA;
结束;
程序TTintimpl1.SetA(常量值:整数);
变量
a:整数;
开始
FA:=值*10;
书面语(“SetA”,FA);
结束;
{2}
//应该被调用-但是第一个实现的父级被调用
过程2.MySetA(常量值:整数);
开始
FA:=值*20;
书面形式(“在迈塞塔”,FA);
结束;
开始
Form5:=TMain.Create;
尝试
Form5.FormCreate;
最后
表格5.免费;
readln;
结束;
结束。
我做错了什么

谢谢

伊布。
Delphi 10.2 Tokyo Win64

如果不使用interface@DavidHeffernan-只有在使用RTTI时才会忽略接口解析。当我在代码中设置属性时,它会按预期工作。您能指导我如何正确地设置声明的接口属性吗g RTTI。谢谢。你需要通过接口。你的RTTI代码通过类。谢谢David。是的,当我通过接口访问方法时,它可以工作。但不幸的是,没有为接口属性生成RTTI(正如有人所说)只是语法糖。重写逻辑更容易避免麻烦的接口。无论如何,谢谢。你必须直接调用属性getter和setter,但是你可以通过RTTI来实现