我需要帮助:
我将对象属性存储在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;
关于如何定义,存储和检索它的任何想法?
对不起给予长时间的解释,并提前感谢您的帮助
迈克尔
答案 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的泛型支持集。