4

2日前から、私は自分の簡単なクラスをゼロから作り始めましたTObject。また、ファイルとの間で書き込み/読み取りを行う必要があったため、検索した後、シリアル化の詳細をすべて学習しておらず、完全に取得していないため、ここからシリアル化メソッドを借用しました。私がそれをテストしていたので、それはうまくいきました。次に、別のクラスをプロパティとして追加しました(これは、sup-propertyと言うときに参照しています:クラスのプロパティであるクラスのプロパティ...紛らわしいですが、適切な名前が必要です)。これそれを実際に行う方法についての質問です。これで、ファイルへの書き込みでエラーが発生することはないようですが、サブプロパティが正しく書き込まれているか、単なるゴミであるかはわかりません。しかし、それを読み返すと、

メッセージ「無効なプロパティタイプ:TSomething」を含む例外クラスEPropertyConvertError

私はこれを学んでいるだけなので、何が悪いのかわかりません。私はいくつかの野蛮な推測を持っていますが、そのうちの1つは、TSomething = Classおそらく独自のシリアル化メソッドを持っている必要があるということですか?その場合、それはどのように機能しますか(私でさえこの仮定を信じていないため)?もう1つは、delphi.about.comから借用したコードでは、これらのタイプのプロパティを処理できないということです。もしそうなら、どうすればそれを改善できますか?そして、私の推測のどれも正しくない場合、これをどのように機能させるでしょうか?(そして私はDelphiXE2を使用しています。)

リクエストに応じたコード:

TSomething = Class
protected
  fNumber: integer;
  fLine: string;
public
  procedure Assign(Source: TObject);
published
  property Number: integer read fNumber write fNumber;
  property Line: string read fLine write fLine;
End;

TOther = Class
public
  procedure LoadFromStream(const Stream: TMemoryStream);
  procedure SaveToStream(const Stream: TMemoryStream);
  constructor Create; virtual;
  destructor Destroy; override;
protected
  fSomething: TSomething;
  procedure SetfSmth(AValue: TSomething);
published
  property Something: TSomething read fSomething write SetfSomething;
end;

メソッドの実装は、上記で提供された2つのリンクから借用されています。要求されない限り、再入力する必要はないと思います。

4

2 に答える 2

3

TSomethingをシリアル化するには、サブコンポーネントである必要があります。これを行うには、1つのことを変更する必要があります。2つのクラスをTObjectから派生させるのではなく、TComponentから派生させることです。次に、TSomethingコンストラクターで呼び出します

Self.SetSubComponent(True);

最後に、クラスはTComponentであるため、 WriteComponent / ReadComponentを使用してTComponentをTStreamで直接シリアル化できるため、delphi.aboutから取得したものはもう必要ありません。

適切な子孫を選択すると、プロセスが簡単になることがわかります。ここでの選択はロジックです。シリアル化する場合は、TComponentを使用します。

于 2012-06-30T15:23:39.777 に答える
1

TSomethingクラスに独自のシリアル化メソッドを与えるというアイデアをフォローアップする必要があると思います。

シリアル化にXMLを使用する例を次に示します。

TSomething = class(TPersistent)
protected
  FNumber: Integer;
  FLine: String;
public
  procedure WriteToXmlNode(XmlNode: IXmlNode);
  procedure ReadFromXmlNode(XmlNode: IXmlNode);
published
  property Number: Integer read FNumber write FNumber;
  property Line: String read FLine write FLine;
end;

TOther = class(TPersistent)
protected
  FSomething: TSomething;
public
  procedure WriteToXmlNode(XmlNode: IXmlNode);
  procedure ReadFromXmlNode(XmlNode: IXmlNode);
published
  property Something: TSomething read FSomething write FSomething;
end;

つまり、各クラスにXMLにシリアル化する方法を知らせます。

TOtherの書き込みメソッドは次のようになります。

procedure TOther.WriteToXmlNode(XmlNode: IXmlNode)
var
  ChildNode: IXmlNode;
begin
  // Write something
  ChildNode := XmlNode.AddChild('Something');
  Something.WriteToXmlNode(ChildNode);       
end;

そして、readメソッドは次のようになります。

procedure TOther.ReadFromXmlNode(XmlNode: IXmlNode)
var
  ChildNode: IXmlNode;
begin
  // Read
  ChildNode := XmlNode.ChildNodes.First;
  while Assigned(ChildNode) do
  begin
    // Read something
    if ChildNode.NodeName = 'Something' then
      Something.ReadFromXmlNode(ChildNode);

    // Next child node
    ChildNode := ChildNode.NextSibling;
  end;
end;

それがその一般的な要点です。

XMLにシリアル化することを選択しなくても、例では同様のアプローチを使用すると思います。

編集:あなたがあなたの質問で何を望んでいたかは少し不明確でした。コンポーネントを作成していて、設計時にコンポーネントを操作するときにコンポーネントのプロパティを適切にシリアル化する必要がある場合、これは適切な方法ではありません。私が説明する方法は、実行時に任意のオブジェクトをシリアル化するためのものです。

于 2012-06-30T16:21:36.520 に答える