First:
Result := TIntegerProperty(FProperties.Objects[Pos]).Value
Is risky because you will crash if it is not a TIntegerProperty.
Use something like:
Pos := FProperties.IndexOf(APropertyName);
if (Pos >= 0) and (FProperties.Objects[Pos] is TIntegerProperty) then
Result := TIntegerProperty(FProperties.Objects[Pos]).Value
else
Result := 0;
Next the status, I don't think you need them al:
For the list
- Deleted a child: Deleted
- Added a child: Added
- Child had been changed: ChildsModified
You don't need unchanged because in that case, the set is empty. And you don't need Modified because in that case the set is not empty.
For the properties you can just add a Changed value.
You can add ChildsModified directly if a child is changed. Or you can use lazy evaluation and walk all children to check for Changed.
Ok you can do something like this:
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;
And off course add support for deletion.
You can let the Property handle all changes (Add when constructed and Delete when freed).