Состояние объекта (подсеть) Постоянство - PullRequest
3 голосов
/ 20 марта 2009

Мне нужна помощь по этому вопросу:

сохранение свойств объекта в классе 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;

есть идеи, как я могу определить, сохранить и получить его?

извините за длинное объяснение и заранее спасибо за помощь

Michael

Ответы [ 2 ]

1 голос
/ 21 марта 2009

Если вы храните свойства объекта, и одно из этих свойств должно быть свойством статуса, то все, что вам в конечном итоге нужно сделать, это то же самое, что вы сделали для TIntegerProperty, но заменить Integer на * 1003. *.

Сначала определите другой класс свойств, который содержит ваше значение TObjectStatus:

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

Затем добавьте методы в ваш пакет данных для работы с этим типом свойства:

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 классов, которые необходимо написать, если у вас был Delphi 2009 и если наборы обобщений Delphi поддерживали.

1 голос
/ 20 марта 2009

Первый:

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;

Следующий статус, я не думаю, что они вам нужны al:

Для списка - Удален ребенок: Удален - добавлен ребенок: добавлен - Ребенок был изменен: 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;

И, конечно, добавить поддержку удаления.

Вы можете позволить свойству обрабатывать все изменения (добавить при построении и удалить при освобождении).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...