10

私はこの質問に自分で答えますが、あなたが私より速い場合、または私の解決策が気に入らない場合は、遠慮なく答えてください。私はちょうどこのアイデアを思いついたので、それについていくつか意見を述べたいと思います。

目標: (INI ファイルのように) 読み取り可能であるが、load および save メソッドを記述する (そして新しい構成項目が追加された後に適応する) 必要がない構成クラス。

のようなクラスを作りたい

TMyConfiguration = class (TConfiguration)
  ...
  property ShowFlags : Boolean read FShowFlags write FShowFlags;
  property NumFlags : Integer read FNumFlags write FNumFlags;
end;

TMyConfiguration.Save (TConfiguration から継承) を呼び出すと、次のようなファイルが作成されます。

[Options]
ShowFlags=1
NumFlags=42

質問:これを行う最善の方法は何ですか?

4

7 に答える 7

7

これが私の提案する解決策です。

私は基本クラスを持っています

TConfiguration = class
protected
  type
    TCustomSaveMethod = function  (Self : TObject; P : Pointer) : String;
    TCustomLoadMethod = procedure (Self : TObject; const Str : String);
public
  procedure Save (const FileName : String);
  procedure Load (const FileName : String);
end;

Load メソッドは次のようになります (それに応じて Save メソッド)。

procedure TConfiguration.Load (const FileName : String);
const
  PropNotFound = '_PROP_NOT_FOUND_';
var
  IniFile : TIniFile;
  Count : Integer;
  List : PPropList;
  TypeName, PropName, InputString, MethodName : String;
  LoadMethod : TCustomLoadMethod;
begin
  IniFile := TIniFile.Create (FileName);
  try
    Count := GetPropList (Self.ClassInfo, tkProperties, nil) ;
    GetMem (List, Count * SizeOf (PPropInfo)) ;
    try
      GetPropList (Self.ClassInfo, tkProperties, List);
      for I := 0 to Count-1 do
        begin
        TypeName  := String (List [I]^.PropType^.Name);
        PropName  := String (List [I]^.Name);
        InputString := IniFile.ReadString ('Options', PropName, PropNotFound);
        if (InputString = PropNotFound) then
          Continue;
        MethodName := 'Load' + TypeName;
        LoadMethod := Self.MethodAddress (MethodName);
        if not Assigned (LoadMethod) then
          raise EConfigLoadError.Create ('No load method for custom type ' + TypeName);
        LoadMethod (Self, InputString);
        end;
    finally
      FreeMem (List, Count * SizeOf (PPropInfo));
    end;
  finally
    FreeAndNil (IniFile);
  end;

基本クラスは、Delphi のデフォルト タイプのロード メソッドとセーブ メソッドを提供できます。次に、次のようにアプリケーションの構成を作成できます。

TMyConfiguration = class (TConfiguration)
...
published
  function  SaveTObject (P : Pointer) : String;
  procedure LoadTObject (const Str : String);
published
  property BoolOption : Boolean read FBoolOption write FBoolOption;
  property ObjOption : TObject read FObjOption write FObjOption;
end;

カスタム保存方法の例:

function TMyConfiguration.SaveTObject (P : Pointer) : String;
var
  Obj : TObject;
begin
  Obj := TObject (P);
  Result := Obj.ClassName;  // does not make sense; only example;
end;       
于 2009-08-18T12:35:02.380 に答える
6

私は構成の手段として、すべてのアプリケーションで XML を使用しています。それは:

  • フレキシブル
  • 将来の機能証明
  • どんなテキストリーダーでも読みやすい
  • アプリケーションでの拡張が非常に簡単です。クラスの変更は必要ありません

欠損値を監視する必要さえなく、構成の読み取りや変更を非常に簡単にする XML ライブラリがあります。XML をアプリケーション内のクラスにマップして、速度が問題になる場合や特定の値が常に読み取られる場合に、より高速にアクセスできるようになりました。

他の構成方法はオプションではありません。

  • Ini ファイル: 詳細な構造がなく、柔軟性がはるかに低い
  • レジストリ: それには近づかないでください。
于 2009-08-18T13:29:15.027 に答える
3

私の好みの方法は、グローバルインターフェイスユニットにインターフェイスを作成することです。

type
  IConfiguration = interface
    ['{95F70366-19D4-4B45-AEB9-8E1B74697AEA}']
    procedure SetConfigValue(const Section, Name,Value:String);
    function GetConfigValue(const Section, Name:string):string;
  end;

このインターフェースは、私のメインフォームで「公開」されます。

type
  tMainForm = class(TForm,IConfiguration)
  ...
  end;

ほとんどの場合、実際の実装はメインフォームではなく、単なるプレースホルダーであり、implementsキーワードを使用して、メインフォームが所有する別のオブジェクトにインターフェイスをリダイレクトします。これのポイントは、構成の責任が委任されているということです。各ユニットは、構成がテーブル、iniファイル、xmlファイル、または(gasp)レジストリに保存されているかどうかを気にしません。これにより、グローバルインターフェイスユニットを使用するユニットで実行できることは、次のような呼び出しを行うことです。

var
  Config : IConfiguration;
  Value : string;
begin
  if Supports(Application.MainForm,IConfiguration,Config) then
    value := Config.GetConfiguration('section','name');
  ...      
end;

必要なのは、作業中のユニットにFORMSとグローバルインターフェイスユニットを追加することだけです。また、メインフォームを使用しないため、後で別のプロジェクトで再利用することにした場合は、それ以上の変更を行う必要はありません。構成ストレージスキームが完全に異なっていても、機能します。

私の一般的な好みは、テーブル(データベースアプリケーションを扱っている場合)またはXMLファイルを作成することです。マルチユーザーデータベースアプリケーションの場合は、2つのテーブルを作成します。1つはグローバル構成用で、もう1つはユーザー構成用です。

于 2009-08-18T15:58:34.123 に答える
1

基本的に、特定のオブジェクトをシリアル化するソリューションを求めています (この場合は、ini ファイルへの構成)。そのための既製のコンポーネントがあり、ここここを探し始めることができます。

于 2009-08-18T12:40:04.237 に答える
1

少し前に、同じタスクのために小さなユニットを書きました-アプリケーションの構成をxmlファイルに保存/ロードします。

フリーウェア SMComponent ライブラリの Obj2XML.pas ユニットを確認してください: http://www.scalabium.com/download/smcmpnt.zip

于 2009-08-19T14:59:04.560 に答える
0

ニックスの回答 (Java プロパティを使用) にはポイントがあります。アプリケーションの部分間で構成を読み取って渡すこの単純な方法は、特別な構成クラスへの依存関係を導入しません。単純なキーと値のリストを使用すると、アプリケーション モジュール間の依存関係が減り、コードの再利用が容易になります。

Delphi では、単純な TStrings ベースの構成は、構成を実装する簡単な方法です。例:

mail.smtp.host=192.168.10.8    
mail.smtp.user=joe    
mail.smtp.pass=*******
于 2009-08-22T07:33:18.880 に答える
0

これはJava用です。

構成ファイルまたはプロパティー・ファイルを読み取るためにjava.util.Propertiesクラスを使用するのが好きです。私が気に入っているのは、上記と同じ方法でファイルを行で配置することです(キー=値)。また、多くのスクリプト言語と同様に、コメント行に # (ポンド記号) を使用します。

したがって、次を使用できます。

ShowFlags=true
# this line is a comment    
NumFlags=42

次に、次のようなコードがあります。

Properties props = new Properties();
props.load(new FileInputStream(PROPERTIES_FILENAME));
String value = props.getProperty("ShowFlags");
boolean showFlags = Boolean.parseBoolean(value);

そのように簡単。

于 2009-08-18T12:39:08.403 に答える