delphi - 对象状态(子集)持久化

标签 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;

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

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

  TObjectStatus = Set of TStatus;

关于如何定义、存储和检索它有什么想法吗?

抱歉这么长的解释,并提前感谢您的帮助

迈克尔

最佳答案

第一:

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;

接下来是状态,我认为您不需要它们:

查看列表 - 删除了一个 child :已删除 - 添加了一个 child :添加了 - 子项已更改:ChildsModified

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

对于属性,您只需添加更改值即可。 如果子项发生更改,您可以直接添加 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;

当然还要添加对删除的支持。

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

关于delphi - 对象状态(子集)持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/667897/

相关文章:

Delphi - 接口(interface)作为另一个接口(interface)

json - Delphi - 在运行时解析 JSON 数据时发生访问冲突

delphi - 如何在不禁用 UAC 的情况下在 Windows 7 上运行 Delphi 7?

delphi - 为什么要保留字符串变量来执行 TStringStream 的默认初始化?

hibernate - JPA 脏检查

java - 是否可以在单独的类/文件中映射 Hibernate 的普通 Java bean?

c++ - 使用 RapidXML 在 C++ 中更新 XML 节点和属性值

python - 比较列表和 dictview

java - 如何获取对循环内部创建的集合的引用?

Java Streams - 提取嵌套对象和组