2009-03-20 8 views
3

J'ai besoin d'aide à ce sujet:Statut de l'objet (sous-ensemble) Persistance

Im stocker des propriétés d'objet dans une classe DataPacket. Les propriétés sont définies comme celui-ci

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; 

la classe DataPacket:

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

et ils sont mis en œuvre comme:

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; 

maintenant la question: je dois définir une propriété d'état défini comme TObjectStatus où:

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

    TObjectStatus = Set of TStatus; 

une idée sur comment puis-je le définir, le stocker et le récupérer?

désolé pour la longue explication et merci à l'avance pour vous aider à

Michael

Répondre

1

Première:

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

est risqué parce que vous écrasez si ce n'est pas un TIntegerProperty. Utilisez quelque chose comme:

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

Suivant l'état, je ne pense pas que vous avez besoin al:

Pour la liste - supprimé un enfant: supprimé - Ajout d'un enfant: Ajout - Enfant a été modifié: ChildsModified

Vous n'avez pas besoin d'être modifié car dans ce cas, l'ensemble est vide. Et vous n'avez pas besoin de Modifié car dans ce cas l'ensemble n'est pas vide.

Pour les propriétés, vous pouvez simplement ajouter une valeur modifiée. Vous pouvez ajouter ChildsModified directement si un enfant est modifié. Ou vous pouvez utiliser l'évaluation paresseuse et marcher tous les enfants pour vérifier Changed.

Ok, vous pouvez faire quelque chose comme ceci:

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; 

Et bien sûr ajouter de soutien à la suppression.

Vous pouvez laisser la propriété gérer tous les changements (Ajouter lorsque construit et Supprimer lorsqu'il est libéré).

1

Si vous stockez les propriétés d'objet, et l'une de ces propriétés devrait être une propriété d'état, tout ce que vous devez faire est finalement la même chose que ce que vous avez fait pour TIntegerProperty, mais en remplaçant Integer avec TObjectStatus.

D'abord, définir une autre catégorie de biens qui tient votre valeur TObjectStatus:

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

Ensuite, ajouter des méthodes à votre paquet de données pour travailler avec ce type de propriété:

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; 

Cela pourrait être un grande opportunité d'utiliser des génériques pour réduire le nombre de TXProperty classes que vous devez écrire, si vous aviez Delphi 2009 et si Delphi ' s jeux génériques pris en charge.