首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象状态(SubSet)持久性

对象状态(SubSet)持久性
EN

Stack Overflow用户
提问于 2009-03-20 20:42:47
回答 2查看 274关注 0票数 3

我需要你的帮助:

我将对象属性存储在一个DataPacket类中。属性的定义如下

代码语言:javascript
复制
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类:

代码语言:javascript
复制
type
  TDataPacket = class
  private
    FProperties: TStringList;
  public
    function GetIntegerValue(const APropertyName: string): integer;
    .....
    procedure SetIntegerValue(const APropertyName: string; AValue: integer);
end;

它们的实现方式如下:

代码语言:javascript
复制
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属性,其中:

代码语言:javascript
复制
type
  TStatus = (Deleted, Unchanged, Added , Modified, ChildsModified);

  TObjectStatus = Set of TStatus;

有没有关于如何定义、存储和检索它的想法?

很抱歉长篇大论的解释,并提前感谢您的帮助

迈克尔

EN

回答 2

Stack Overflow用户

发布于 2009-03-20 20:52:56

首先:

代码语言:javascript
复制
Result := TIntegerProperty(FProperties.Objects[Pos]).Value

是有风险的,因为如果它不是TIntegerProperty,就会崩溃。使用像这样的东西:

代码语言:javascript
复制
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。或者,您可以使用惰性评估并遍历所有的孩子来检查是否发生了更改。

好的,你可以这样做:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2009-03-21 15:42:59

如果您要存储一个对象的属性,并且其中一个属性应该是status属性,那么您最终需要做的就是与对TIntegerProperty所做的相同,只是用TObjectStatus替换Integer

首先,定义另一个保存TObjectStatus值的属性类:

代码语言:javascript
复制
type
  TObjectStatusProperty = class(TProperty)
  private
    FValue: TObjectStatus;
  protected
    procedure SetValue(const AValue: TObjectStatus);
  public
    property Value: TObjectStatus read FValue write SetValue;
  end;

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

代码语言:javascript
复制
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;

这可能是一个使用泛型来减少您需要编写的TXProperty类数量的好机会,如果您有Delphi2009并且Delphi的泛型支持集。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/667897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档