1

私はボイラープレート機能を実装しています - ユーザーがいくつかのコンポーネントの説明を変更できるようにします - TLabels のように - 実行時に。例えば

TFooClass = Class ( TBaseClass)
 Label : Tlabel;
 ...
 End;

 Var FooClass : TFooClass;

...

設計時には、Label のキャプション プロパティの値は「First Name」です。アプリケーションの実行時に、ユーザーがキャプション値を「Other Name」に変更できる機能があります。これが変更されると、FooClass のクラス インスタンスのラベルのキャプションがすぐに更新されます。

現在の問題は、ユーザーが何らかの理由で 'First Name' などの設計時の値に戻したい場合、それは不可能に思えることです。

私はRTTIContextメソッドとそのすべてを使用できますが、結局のところ、値を変更するにはクラスのインスタンスが必要なようで、これはすでに変更されているため、レンガの壁にぶつかったようですそれを回避する。

私の質問はこれです-クラスをインスタンス化せずに、クラスのメンバーのプロパティに古いRTTIメソッドまたは新しいRTTIContextのものを使用する方法はありますか-つまり、ClassType定義からプロパティを取得します。

これは私の試みのコードスニペットです:

  c : TRttiContext;
   z : TRttiInstanceType;
   w : TRttiProperty;
 Aform : Tform;
  ....
 Begin
 .....

   Aform := Tform(FooClass);

   for vCount := 0 to AForm.ComponentCount-1 do begin
    vDummyComponent := AForm.Components[vCount];
    if IsPublishedProp(vDummyComponent,'Caption') then begin
      c := TRttiContext.Create;
       try
         z := (c.GetType(vDummyComponent.ClassInfo) as TRttiInstanceType);
         w := z.GetProperty('Caption');
          if w <> nil  then
             Values[vOffset, 1] := w.GetValue(vDummyComponent.ClassType).AsString
        .....
        .....

....
....

あらゆる種類のエラーが発生しています。どんな助けでも大歓迎です。

4

4 に答える 4

1

あなたがしようとしているのは、DFM で定義されている特定のプロパティの値を取得することです。RTTI はクラス定義で指定されたオブジェクトの構造の検査に基づいているため、これは RTTI を使用して行うことはできません。 DFM はクラス定義の一部ではありません。これは、オブジェクトがクラス定義から作成された後にオブジェクトに適用されるプロパティ リストです。

フォームのコントロールのプロパティの値を取得したい場合は、おそらくそれらをどこかにキャッシュする必要があります。OnCreateすべてのコントロールを通過し、RTTI を使用してTDictionary<string, TValue>すべてのプロパティの値を入力するフォームに何かを入れてみてください。その後、必要なときにそれらを調べることができます。

于 2010-04-19T16:07:36.170 に答える
1

RTTI システムは、あなたが求めているものを提供しません。型情報は現在、コンパイル時にのみ決定されます。初期フォーム値は、DFM リソースを使用して実行時に設定されます。DFM リソースは実行時に評価されるため、コンパイル済みアプリケーションの DFM リソースの値を変更できます。

保存されている DFM リソースを解析して使用するか、実行時に元の値のコピーを作成します。おそらく、メモリ フットプリントを削減するための最初の変更の時点で。

石工の使用の提案TDictionary<string, TValue>は、私が使用するものです。この情報をデータベースに保存する際には注意が必要です。同期を維持することは、実際のメンテナンスの悪夢になる可能性があるからです。

于 2010-04-20T04:39:20.647 に答える
0

まあ-私は問題を解決しました。トリックは基本的に次のようなフォームの別のインスタンスをインスタンス化することです:

 procedure ShowBoilerPlate(AForm : TForm; ASaveAllowed : Boolean);
 var
    vCount           : Integer;
    vDesignTimeForm  : TForm;
    vDesignTimeComp  : TComponent;
    vDesignTimeValue : String;
    vCurrentValue    : String;
 begin
   ....
   ....
   vDesignTimeForm :=  TFormClass(FindClass(AForm.ClassName)).Create(AForm.Owner);

   try
     // Now I have two instances of the form - I also need to have at least one
     // overloaded constructor defined for the base class of the forms that will allow for 
     // boilerplating. If you call the default Constructor - no boilerplating
     // is done. If you call the overloaded constructor, then, boilerplating is done.
     // Bottom line, I can have two instances AForm - with boilerplated values and
     // vDesignForm without boilerplated values.
     for vCount := 0 to AForm.ComponentCount-1 do begin
       vDummyComponent := AForm.Components[vCount];
       if Supports (vDummyComponent,IdoGUIMetaData,iGetGUICaption)  then begin
          RecordCount := RecordCount + 1;
          Values[vOffset, 0] := vDummyComponent.Name;
          if IsPublishedProp(vDummyComponent,'Caption') then begin
           vDesignTimeComp := vDesignTimeForm.FindComponent(vDummyComponent.Name);
           if vDesignTimeComp <> nil then begin
             // get Design time values here
              vDesignTimeValue := GetPropValue(vDesignTimeComp,'Caption');
           end;
           // get current boilerplated value here
              vCurrentValue  := GetPropValue(vDummyComponent,'Caption');
         end;
        vOffset := RecordCount;;
       end;
     end;

  finally
    FreeAndNil(vDesignTimeForm);
  end;
end;

とにかく-すべてのアドバイスをありがとうございました。

于 2010-04-23T15:42:38.127 に答える
0

設計時に設定された値 (つまり、DFM に保存されている値) を復元するためにそれを達成しようとしている場合はInitInheritedComponent、出発点として使用します。

実行時に DFM のコンテンツを取得できます。ただし、解析するのは面倒かもしれません。

もチェックしてくださいInternalReadComponentRes

どちらのルーチンもクラス ユニットにあります。

于 2010-04-19T17:32:15.743 に答える