我需要你的帮助:
我将对象属性存储在一个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;有没有关于如何定义、存储和检索它的想法?
很抱歉长篇大论的解释,并提前感谢您的帮助
迈克尔
发布于 2009-03-20 20:52:56
首先:
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;当然也增加了对删除的支持。
您可以让属性处理所有更改(构造时添加,释放时删除)。
发布于 2009-03-21 15:42:59
如果您要存储一个对象的属性,并且其中一个属性应该是status属性,那么您最终需要做的就是与对TIntegerProperty所做的相同,只是用TObjectStatus替换Integer。
首先,定义另一个保存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类数量的好机会,如果您有Delphi2009并且Delphi的泛型支持集。
https://stackoverflow.com/questions/667897
复制相似问题