D2010でRTTIを使用してオブジェクトを複製しようとしています。ここに私の試みはこれまでのところです:Delphi: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.
少しがっかり、私は「A TPersonが解放された複数の発生を見ません「。
オーバーライドされたデストラクタを呼び出すのを手伝ってもらえますか?(そして、なぜそれが呼び出されないのかを説明してください)それは先のタイプを知る必要がありますが、最初の場所。)ありがとう!
ありがとうございます!それは魅力のように働く。ホーマー・シンプソンの言葉を引用すると:D'oh! (これは私の最初のことではないが、うまくいけば最後の、欠けている 'var'に噛まれる時間)。 – conciliator
ああ、サイドノートに:クローンが明示的にnilに設定されていないにもかかわらずAVを取得していない。 – conciliator
@conciliator:うん、明示的に設定しないと、その値が何であるかわからないことを意味します。何もない可能性があります。これは、あなたのコードが予期しない動作をする可能性があることを意味します。なぜなら、前回のCloneのアドレスで発生した値に依存するからです。そして、AVはいつもすぐに起こるわけではありません。クラスのフィールドを使用しないメソッドだけを呼び出すと、年齢を問わずうまくいく可能性があります。それで、あなたが後ろであなたを噛んだとき、あなたはそれがどこから来ているのか把握しようとしているひどい時を過すでしょう。 TLDR:常に変数を初期化します。 –