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

Delphi:重写方法没有调用使用RTTI实例化的对象

发布时间:2020-12-15 09:17:46 所属栏目:大数据 来源:网络整理
导读:我正试图在D2010中使用RTTI克隆对象.这是我到目前为止的尝试: uses SysUtils,TypInfo,rtti;type TPerson = class(TObject) public Name: string; destructor Destroy(); Override; end;destructor TPerson.Destroy;begin WriteLn('A TPerson was freed.');
我正试图在D2010中使用RTTI克隆对象.这是我到目前为止的尝试:

uses SysUtils,TypInfo,rtti;
type
  TPerson = class(TObject)
  public
    Name: string;
    destructor Destroy(); Override;
  end;
destructor TPerson.Destroy;
begin
  WriteLn('A TPerson was freed.');
  inherited;
end;
procedure CloneInstance(SourceInstance: TObject; DestinationInstance: TObject; Context: TRttiContext); Overload;
var
  rSourceType:      TRttiType;
  rDestinationType: TRttiType;
  rField:           TRttiField;
  rSourceValue:     TValue;
  Destination:      TObject;
  rMethod:          TRttiMethod;
begin
  rSourceType := Context.GetType(SourceInstance.ClassInfo);
  if (DestinationInstance = nil) then begin
    rMethod := rSourceType.GetMethod('Create');
    DestinationInstance := rMethod.Invoke(rSourceType.AsInstance.MetaclassType,[]).AsObject;
  end;
  for rField in rSourceType.GetFields do begin
    if (rField.FieldType.TypeKind = tkClass) then begin
      // TODO: Recursive clone
    end else begin
      // Non-class values are copied (NOTE: will cause problems with records etc.)
      rField.SetValue(DestinationInstance,rField.GetValue(SourceInstance));
    end;
  end;
end;
procedure CloneInstance(SourceInstance: TObject; DestinationInstance: TObject); Overload;
var
  rContext:       TRttiContext;
begin
  rContext := TRttiContext.Create();
  CloneInstance(SourceInstance,DestinationInstance,rContext);
  rContext.Free();
end;
var
  Original:     TPerson;
  Clone:        TPerson;
begin
  ReportMemoryLeaksOnShutdown := true;
  Original := TPerson.Create();
  CloneInstance(Original,Clone);
  Clone.Free();
  Original.Free();
  ReadLn;
end.

有点令人失望的是,我没有看到一个“TPerson被释放”的事件.到输出(通过单步执行程序确认) – 只使用重写的析构函数销毁原始文件.

任何人都可以请你帮我调用被覆盖的析构函数吗? (也许可以解释为什么不首先调用它.)谢谢!

解决方法

几个问题与您的代码.

您没有将Clone变量初始化为nil.我的机器上的哪个导致上层CloneInstance方法中的访问冲突,因为没有创建克隆,因为传入的值是非零的.

您没有将DestinationInstance参数声明为var.这意味着上层CloneInstance方法中的实例化不会返回给调用者.将var添加到参数可以解决问题.你需要在程序的main方法中调用CloneInstance时使用TObject(Clone),否则Delphi会抱怨“没有可以使用这些参数调用的重载方法”.这是因为var参数需要将它们的确切声明类型传递给它们.

我将您的代码更改为:

uses
  SysUtils,rtti;

type
  TPerson = class(TObject)
  public
    Name: string;
    constructor Create;
    destructor Destroy(); Override;
  end;

constructor TPerson.Create;
begin
  WriteLn('A TPerson was created');
end;

destructor TPerson.Destroy;
begin
  WriteLn('A TPerson was freed.');
  inherited;
end;

procedure CloneInstance(SourceInstance: TObject; var DestinationInstance: TObject; Context: TRttiContext); Overload;
var
  rSourceType:      TRttiType;
  rDestinationType: TRttiType;
  rField:           TRttiField;
  rSourceValue:     TValue;
  Destination:      TObject;
  rMethod:          TRttiMethod;
begin
  rSourceType := Context.GetType(SourceInstance.ClassInfo);
  if (DestinationInstance = nil) then begin
    rMethod := rSourceType.GetMethod('Create');
    DestinationInstance := rMethod.Invoke(rSourceType.AsInstance.MetaclassType,rField.GetValue(SourceInstance));
    end;
  end;
end;

procedure CloneInstance(SourceInstance: TObject; var DestinationInstance: TObject); Overload;
var
  rContext:       TRttiContext;
begin
  rContext := TRttiContext.Create();
  CloneInstance(SourceInstance,rContext);
  rContext.Free();
end;

var
  Original:     TPerson;
  Clone:        TPerson;
begin
  Clone := nil;
  ReportMemoryLeaksOnShutdown := true;
  Original := TPerson.Create();
  Original.Name := 'Marjan';

  CloneInstance(Original,TObject(Clone));
  Original.Name := 'Original';
  WriteLn('Original name: ',Original.Name);
  WriteLn('Clone name: ',Clone.Name);

  Clone.Free();
  Original.Free();
  ReadLn;
end.

我添加了一个构造函数来查看正在创建的两个实例以及在克隆之后检查名称的几行.输出如下:

A TPerson was created
A TPerson was created
Original name: Original
Clone name: Marjan
A TPerson was freed.
A TPerson was freed.

(编辑:李大同)

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

    推荐文章
      热点阅读