加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

具有单个getter和setter的Delphi属性

发布时间:2020-12-15 09:21:05 所属栏目:大数据 来源:网络整理
导读:我正在尝试实现一个配置文件类包装器,并且使用单个函数获取和使用单个函数将值设置为属性会更容易. 下面的代码是我想要实现的最低版本. 欢迎任何帮助. unit Config;interfaceuses Rtti;type Group = class(TCustomAttribute) strict private FName: string;
我正在尝试实现一个配置文件类包装器,并且使用单个函数获取和使用单个函数将值设置为属性会更容易.

下面的代码是我想要实现的最低版本.

欢迎任何帮助.

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知道的唯一方法是使用索引说明符,例如:

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查找具有相应索引值的属性,如果找到,则还可以访问其属性,例如:

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) then
  begin
    //...
  end;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读