gpt4 book ai didi

具有单个 getter 和 setter 的 Delphi 属性

转载 作者:行者123 更新时间:2023-12-03 15:22:06 27 4
gpt4 key购买 nike

我正在尝试实现一个配置文件类包装器,并且使用单个函数来获取属性并使用单个函数来设置属性值会更容易。

下面的代码是我想要实现的最小版本。

欢迎任何帮助。

unit Config;

interface

uses Rtti;

type
Group = class(TCustomAttribute)
strict private
FName: string;

public
constructor Create(const Name: string);

property Name: string read FName;
end;

IConfig = class
protected
function GetString: string;
procedure SetString(const Value: string);
end;

TConfig = class(IConfig)
public
[Group('Person')]
property Name: string read GetString write SetString;
[Group('Person')]
property City: string read GetString write SetString;
end;

implementation

{ Group }

constructor Group.Create(const Name: string);
begin
FName := Name;
end;

{ IConfig }

function IConfig.GetString: string;
begin
// Here I would need the following from the property that call this function:
// * Property name
// * Property attribute name

// This kind of code will not work, because it loop through all available properties
(*
var
ctx: TRttiContext;
objType: TRttiType;
Prop: TRttiProperty;
begin
ctx := TRttiContext.Create;
objType := ctx.GetType(Obj.ClassInfo);
for Prop in objType.GetProperties do begin
if Prop.GetClassType is TClassBase then
// do something special with base class properties
else
// standard functionality on all other properties
end;
end;
*)
end;

procedure IConfig.SetString(const Value: string);
begin
// Need the same as above
end;

end.

最佳答案

属性 getter 和 setter 不知道哪个属性正在调用它们。共享 getter/setter 知道这一点的唯一方法是使用 index 说明符,例如:

unit Config;

interface

uses Rtti;

type
Group = class(TCustomAttribute)
strict private
FName: string;

public
constructor Create(const Name: string);

property Name: string read FName;
end;

IConfig = class
protected
function GetString(Index: Integer): string;
procedure SetString(Index: Integer; const Value: string);
end;

TConfig = class(IConfig)
public
[Group('Person')]
property Name: string index 0 read GetString write SetString;
[Group('Person')]
property City: string index 1 read GetString write SetString;
end;

implementation

{ Group }

constructor Group.Create(const Name: string);
begin
FName := Name;
end;

{ IConfig }

function IConfig.GetString(Index: Integer): string;
begin
case Index of
0: begin // Name
...
end;
1: begin // City
...
end;
...
end;
end;

procedure IConfig.SetString(Index: Integer; const Value: string);
begin
// same as above
end;

end.

如果 getter/setter 需要知道属性名称,则可以使用 RTTI 查找具有相应 index 值的属性,如果找到则还可以访问其属性,例如:

function GetPropNameAndGroup(Cls: TClass; PropIndex: Integer; var PropName, GroupName: String): Boolean;
var
Ctx: TRttiContext;
Prop: TRttiProperty;
Attr: TCustomAttribute;
begin
PropName := '';
GroupName := '';
Ctx := TRttiContext.Create;
for Prop in Ctx.GetType(Cls).GetProperties do
begin
if (Prop as TRttiInstanceProperty).Index = PropIndex then
begin
PropName := Prop.Name;
for Attr in Prop.GetAttributes do
begin
if Attr is Group then
begin
GroupName := Group(Attr).Name;
Break;
end;
end;
Break;
end;
end;
Result := (PropName <> '') and (GroupName <> '');
end;

function IConfig.GetString(Index: Integer): string;
var
PropName, GroupName: string;
begin
if GetPropNameAndGroup(ClassType, Index, PropName, GroupName) then
begin
//...
end;
end;

procedure IConfig.SetString(Index: Integer; const Value: string);
var
PropName, GroupName: string;
begin
if GetPropNameAndGroup(ClassType, Index, PropName, GroupName) then
begin
//...
end;
end;

关于具有单个 getter 和 setter 的 Delphi 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25209076/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com