2009-03-20 12 views
3

私はこのことについて助けが必要です:オブジェクトステータス(サブセット)持続性

imはDataPacketクラスにオブジェクトプロパティを格納しています。 プロパティは、この

type 
    TProperty = class 
    private 
    FName: string; 
    public 
    constructor Create(const AName: string); 
    property Name: string read FName; 
    end; 

    TIntegerProperty = class(TProperty) 
    private 
    FValue: Integer; 
    protected 
    procedure SetValue(const AValue:integer); 
    public 
    property Value: Integer read FValue write SetValue; 
    end; 

データパケットのクラスのように定義されています。

type 
    TDataPacket = class 
    private 
    FProperties: TStringList; 
    public 
    function GetIntegerValue(const APropertyName: string): integer; 
    ..... 
    procedure SetIntegerValue(const APropertyName: string; AValue: integer); 
end; 

、彼らは次のように実装されています:

function TDataPacket.GetIntegerValue(const APropertyName: string): integer; 
var 
    Pos: integer; 
begin 
    Pos := FProperties.IndexOf(APropertyName); 
    if Pos > -1 then 
    Result := TIntegerProperty(FProperties.Objects[Pos]).Value 
    else 
    Result := 0; 
end; 

procedure TDataPacket.SetIntegerValue(const APropertyName: string; AValue: integer); 
var 
    Pos: integer; 
    AProperty: TIntegerProperty; 
begin 
    Pos := FProperties.IndexOf(APropertyName); 
    if Pos >- 1 then 
    TIntegerProperty(FProperties.Objects[Pos]).Value := AValue 
    else 
    begin 
     AProperty:= TIntegerProperty.Create(APropertyName); 
     AProperty.Value := AValue; 
     FProperties.AddObject(APropertyName, AProperty); 
    end; 
end; 

質問:私は、定義されたStatusプロパティを定義する必要がありますTObjectStatusとして、

type 
    TStatus = (Deleted, Unchanged, Added , Modified, ChildsModified); 

    TObjectStatus = Set of TStatus; 

どのように私はそれを定義し、保存し、取得することができますか?事前に長い説明と感謝して申し訳ありません

あなたは

マイケルは

答えて

1

まず助けるために:それはTIntegerPropertyでない場合は、クラッシュしますので

Result := TIntegerProperty(FProperties.Objects[Pos]).Value 

は危険です。 使用のようなもの:

Pos := FProperties.IndexOf(APropertyName); 
if (Pos >= 0) and (FProperties.Objects[Pos] is TIntegerProperty) then 
    Result := TIntegerProperty(FProperties.Objects[Pos]).Value 
else 
    Result := 0; 

次のステータスが、私はあなたが彼らにアルが必要とは思わない:

リスト について - 子を削除: を削除した - 子を追加しました: を追加しました - 子供を変更されました:ChildsModified

この場合、セットは空ですので、変更する必要はありません。その場合、セットは空ではないため、Modifiedは必要ありません。

プロパティの場合、変更された値を追加することができます。 子が変更された場合は、ChildsModifiedを直接追加できます。または、遅延評価を使用して、すべての子どもたちがChangedを確認するために歩くことができます。

type 
    TStatus = (stDeleted, stAdded , stModified, stChildsModified); 
    TObjectStatus = Set of TStatus; 


    TDataPacket = class; 
    TProperty = class 
    private 
    FName : string; 
    FParent : TDataPacket; 
    protected 
    procedure NotifyChange(const AStatus: TStatus); 
    public 
    constructor Create(const AParent: TDataPacket; const AName: string); 
    property Name: string read FName; 
    end; 

    TIntegerProperty = class(TProperty) 
    private 
    FValue: Integer; 
    procedure SetValue(const AValue:integer); 
    public 
    property Value: Integer read FValue write SetValue; 
    end; 

    TDataPacket = class 
    private 
    FProperties: TStringList; 
    FStatus : TObjectStatus; 
    protected 
    procedure NotifyChange(const AStatus: TStatus); 

    function GetProperty(const AName: string): TProperty; 
    public 
    function GetIntegerValue(const APropertyName: string): integer; 
    procedure SetIntegerValue(const APropertyName: string; AValue: integer); 
    end; 


procedure TProperty.NotifyChange(const AStatus: TStatus); 
begin 
    FParent.NotifyChange(AStatus); 
end; 

constructor TProperty.Create(const AParent: TDataPacket; const AName: string); 
begin 
    Assert(AParent<>nil); 
    FName := AName; 
    FParent := AParent; 
end; 

procedure TIntegerProperty.SetValue(const AValue:integer); 
begin 
    if AValue<>FValue then begin 
    FValue := AValue; 
    NotifyChange(stChildsModified); 
    end; 
end; 

procedure TDataPacket.NotifyChange(const AStatus: TStatus); 
begin 
    if AProp=nil then begin 
    case AStatus of 

    TStatus = (stDeleted, stAdded , stModified, stChildsModified); 

    FStatus := FStatus + [AStatus]; 
end; 

function TDataPacket.GetProperty(const AName: string): TProperty; 
var 
    i : Integer; 
begin 
    i := FProperties.IndexOf(AName); 
    if i>=0 then 
    Result := TProperty(FProperties.Objects[i]) 
    else 
    Result := nil; 
end; 

function TDataPacket.GetIntegerValue(const APropertyName: string): integer; 
var 
    prop : TProperty; 
begin 
    prop := GetProperty(APropertyName); 
    if (prop<>nil) and (prop is TIntegerProperty) then 
    Result := TIntegerProperty(prop).Value 
    else 
    Result := 0; 
end; 

procedure TDataPacket.SetIntegerValue(const APropertyName: string; AValue: integer); 
var 
    prop : TProperty; 
    intprop : TIntegerProperty; 
begin 
    prop := GetProperty(APropertyName); 
    if (prop<>nil) and not (AProperty is TIntegerProperty) then begin 
    // PANIC! 
    end else begin 
    if prop=nil then begin 
     intprop := TIntegerProperty.Create(self, APropertyName); 
     intprop.Value := AValue; 
     FProperties.AddObject(APropertyName, intprop); 
     NotifyChange(stAdded); 
    end else begin 
     TIntegerProperty(prop).Value := AValue; 
    end; 
    end; 
end; 

を、オフコースの削除のサポートを追加します。[OK]を

あなたはこのような何かを行うことができます。

すべての変更をプロパティに処理させることができます(作成時に追加、解放時に削除)。

1

あなたがオブジェクトのプロパティを保存している、それらの特性の一つは、ステータスプロパティでなければなりません場合は、あなたが最終的に行う必要があるすべてはあなたがTIntegerPropertyのためにやったことと同じであるが、TObjectStatusIntegerを交換します。

function TDataPacket.GetObjectStatusValue(
    const APropertyName: string): TObjectStatus; 
var 
    Pos: integer; 
    Prop: TProperty; 
begin 
    Pos := FProperties.IndexOf(APropertyName); 
    if Pos >= 0 then begin 
    Prop := FProperties.Objects[Pos] as TProperty; 
    Assert(Prop.Name = APropertyName); 
    if Prop is TObjectStatusProperty then 
     Result := TObjectStatusProperty(Prop).Value 
    else 
     raise EWrongPropertyType.CreateFmt('Expected %s but got %s', 
     [TObjectStatusProperty.ClassName, Prop.ClassName]); 
    end else 
    Result := []; 
end; 

procedure TDataPacket.SetObjectStatusValue(
    const APropertyName: string; AValue: TObjectStatus); 
var 
    Pos: integer; 
    Prop: TProperty; 
begin 
    Pos := FProperties.IndexOf(APropertyName); 
    if Pos >= 0 then begin 
    Prop := FProperties.Objects[Pos] as TProperty; 
    Assert(Prop.Name = APropertyName); 
    if Prop is TObjectStatusProperty then 
     TObjectStatusProperty(Prop).Value := AValue 
    else 
     raise EWrongPropertyType.CreateFmt('Expected %s but got %s', 
     [TObjectStatusProperty.ClassName, Prop.ClassName]); 
    end else begin 
    Prop := TObjectStatusProperty.Create(APropertyName); 
    TObjectStatusProperty(Prop).Value := AValue; 
    FProperties.AddObject(APropertyName, Prop); 
    end; 
end; 

これは次のようになります。

まず、あなたのTObjectStatus値を保持別のプロパティクラス定義:

type 
    TObjectStatusProperty = class(TProperty) 
    private 
    FValue: TObjectStatus; 
    protected 
    procedure SetValue(const AValue: TObjectStatus); 
    public 
    property Value: TObjectStatus read FValue write SetValue; 
    end; 

次に、プロパティのタイプで動作するようにあなたのデータパケットにメソッドを追加あなたが書く必要があるクラスの数を減らすためにジェネリックスを使用する素晴らしい機会TXPropertyあなたがDelphi 2009を持っていて、のジェネリックサポートセット。

関連する問題