加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 如何正确使用TRttiMethod.Invoke中的字符串作为参数?

发布时间:2020-12-15 09:48:34 所属栏目:大数据 来源:网络整理
导读:我正在尝试使用RTTI使用Text-property来概括可视组件的内容验证,但是当我尝试将字符串值传递给TRttiMethod.Invoke时,我收到消息“Invalid Typecast”. (实际上是“UngültigeTypumwandlung”,但我猜,这是一个合适的翻译.) 假设所有传递的对象都是完美的,下面
我正在尝试使用RTTI使用Text-property来概括可视组件的内容验证,但是当我尝试将字符串值传递给TRttiMethod.Invoke时,我收到消息“Invalid Typecast”. (实际上是“UngültigeTypumwandlung”,但我猜,这是一个合适的翻译.)

假设所有传递的对象都是完美的,下面的代码将被删除所有安全措施,断言等.

procedure ValidateTextFieldAndSetFocus(const Field: TObject; const Validator: TObject; const errorStates: array of TStringValidationResult; const sErrorMessage: string);
var
  context  : TRttiContext;
  objField : TRttiType;
  objValid : TRttiType;
  prop     : TRttiProperty;
  execute  : TRttiMethod;
  I        : Integer;
  validResult : TStringValidationResult;
  value    : TValue;
begin
  context  := TRttiContext.Create;
  objField := context.GetType(Field.ClassInfo);
  objValid := context.GetType(Validator.ClassInfo);
  prop     := objField.GetProperty('Text');
  value    := prop.GetValue(Field);
  execute  := objValid.GetMethod('Execute');
  for I := 0 to High(errorStates) do
    if execute.Invoke(Validator,[value]).TryAsType<TStringValidationResult>(validResult) then
      if validResult = errorStates[I] then
      begin
        SetFocusIfCan(Field);
        raise Exception.Create(sErrorMessage);
      end;
end;

Validator的Execute只有一个string-Parameter.我已经看过将字符串直接传递到TValue数组的示例,但后来我得到了相同的类型转换错误.

编辑:

实际错误出现在execute.Invoke(Validator,[value])中.

TNoSemicolonNullValidator = class
  class function Execute(const aStr: string): TStringValidationResult;
end;

procedure TestValidation;
var
  Validator : TNoSemicolonNullValidator;
begin
  Validator := TNoSemicolonNullValidator.Create;
  try
    ValidateTextFieldAndSetFocus(Edit1,Validator,[svInvalid],'Edit1 is invalid!');
  finally
    Validator.Free;
  end;
end;

解决方法

您在此处调用类函数,但是您将TObject作为第一个参数传递(这是非静态方法的隐藏Self参数).在类方法上,Self参数不能是实例,而是它的类.所以正确的电话会是:

execute.Invoke(validator.ClassType,[value]);

这是一个证明:

program Project1;

{$APPTYPE CONSOLE}

uses
  Rtti,SysUtils;

type
  TValidator = class
    class function Execute(const s: string): Boolean;
  end;

class function TValidator.Execute(const s: string): Boolean;
begin
  Writeln(s);
end;

var
  ctx: TRttiContext;
  v: TValidator;
begin
  v := TValidator.Create;
  try
    ctx.GetType(TValidator).GetMethod('Execute').Invoke(v,['test']);
  except
    on E: Exception do
      Writeln(E.ClassName,': ',E.Message);
  end;
  try
    ctx.GetType(TValidator).GetMethod('Execute').Invoke(v.ClassType,E.Message);
  end;
  Readln;
end.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读