对象状态(子集)持久性

时间:2009-03-20 20:42:47

标签: delphi persistence set

我需要帮助:

我将对象属性存储在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;

DataPacket类:

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;

现在的问题是:我需要定义一个定义为TObjectStatus的Status属性,其中:

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

  TObjectStatus = Set of TStatus;

关于如何定义,存储和检索它的任何想法?

对不起给予长时间的解释,并提前感谢您的帮助

迈克尔

2 个答案:

答案 0 :(得分:1)

首先:

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

风险很大,因为如果它不是TIntegerProperty,你会崩溃。 使用类似的东西:

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

接下来的状态,我认为你不需要它们:

列表   - 删除了一个孩子:已删除   - 添加了一个孩子:已添加   - 孩子被改变了:ChildsModified

您不需要保持不变,因为在这种情况下,该集合为空。并且您不需要修改,因为在这种情况下该集合不为空。

对于属性,您只需添加更改值即可。 如果更改了子项,您可以直接添加ChildsModified。或者您可以使用延迟评估并让所有孩子检查更改。

好的,你可以这样做:

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;

然后当然添加删除支持。

您可以让属性处理所有更改(构造时添加和释放时删除)。

答案 1 :(得分:1)

如果您要存储对象的属性,并且其中一个属性应该是状态属性,那么您最终需要做的就是与TIntegerProperty所做的相同,但替换{{1}与Integer

首先,定义另一个包含TObjectStatus值的属性类:

TObjectStatus

接下来,向数据包添加方法以使用该类型的属性:

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

如果您使用Delphi 2009,这可能是使用泛型来减少您需要编写的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; T X类的数量的绝佳机会如果Delphi的泛型支持集。