【Delphi】StringList组件进行接口化处理

TStringList是Delphi编程中经常使用到的组件,对它进行接口化处理的主要目的,是实现TStringList的内存自动释放。例如下命的过程,执行完毕后,为aList变量所分配的内存就会自动释放,不需要用aList.free来释放内存,可以有效避免因忘记释放内存而导致内存泄漏。接口中并没有包括全部的TStringList函数或过程,可以根据实际需要进行增减。这个接口化处理方法也适用于其它组件。

uses uStringList;

procedure TForm1.Button1Click(Sender: TObject);
var
  aList: IStringList;
begin
  aList := TStringListIntf.Create;
  aList.Add('Test')
end;
unit uStringlist;

interface

uses System.Classes;

type
  IStringList = interface['{7BC2765C-9289-48EA-AB97-1A73E2AF637F}']
    function Get(Index: Integer): string;
    procedure Put(Index: Integer; const S: string);
    function GetCount: Integer;
    function GetTextStr: string;
    procedure SetTextStr(const Value: string);
    function GetDelimiter: Char;
    procedure SetDelimiter(aChar: Char);
    function GetDelimitedText: String;
    procedure SetDelimitedText(aText: String);
    function GetValue(const Name: string): String;
    procedure SetValue(const Name, Value: string);
    function GetSorted: Boolean;
    procedure SetSorted(Value: Boolean);
    function GetCaseSensitive: Boolean;
    procedure SetCaseSensitive(const Value: Boolean);
    function GetDuplicates: TDuplicates;
    procedure SetDuplicates(const Value: TDuplicates);

    function GetEnumerator: TStringsEnumerator;
    function Add(const S: string): Integer;
    procedure LoadFromFile(const FileName: string);
    function First: String;
    function Last: String;
    procedure Clear;
    procedure BeginUpdate;
    procedure EndUpdate;
    procedure Delete(Index: Integer);
    function AddPair(const Name, Value: string): IStringList;
    procedure Append(const S: string);
    procedure AddStrings(Strings: IStringList);
 // procedure SetStrings(Source : IStringList);
    function IndexOf(const S: string): Integer;
    function IndexOfName(const Name: string): Integer;
    procedure Insert(Index: Integer; const S: string);
    procedure Sort;
    function Find(const S: string; var Index: Integer): Boolean;
    property Strings[Index: Integer]: string read Get write Put; default;
    property Count: Integer read GetCount;
    property Text: string read GetTextStr write SetTextStr;
    property Delimiter: Char read GetDelimiter write SetDelimiter;
    property DelimitedText: string read GetDelimitedText write SetDelimitedText;
    property Values[const Name: string]: string read GetValue write SetValue;
    property Sorted: Boolean read GetSorted write SetSorted;
    property CaseSensitive: Boolean read GetCaseSensitive write SetCaseSensitive;
    property Duplicates: TDuplicates read GetDuplicates write SetDuplicates;
  end;

  TStringListIntf = class
    class function Create: IStringList;
  end;

implementation

type
  TInterfacedStringList = class(TStringList, IStringList)
  private
    const objDestroyingFlag = Integer($80000000);
    function GetRefCount: Integer; inline;
  protected
    [Volatile] FRefCount: Integer;
    class procedure __MarkDestroying(const Obj); static; inline;
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    property RefCount: Integer read GetRefCount;
  protected
    function First: String;
    function Last: String;
    procedure AddStrings(Strings: IStringList); overload;
  //procedure SetStrings(Source : IStringList); overload;
    function AddPair(const Name, Value: string): IStringList; overload;

    function GetDelimiter: Char;
    procedure SetDelimiter(aChar: Char);
    property Delimiter: Char read GetDelimiter write SetDelimiter;

    function GetDelimitedText: String;
    procedure SetDelimitedText(aText: String);
    property DelimitedText: string read GetDelimitedText write SetDelimitedText;

    function GetValue(const Name: string): String;
    procedure SetValue(const Name, Value: string);
    property Values[const Name: string]: string read GetValue write SetValue;

    function GetSorted: Boolean;
    procedure SetSorted(Value: Boolean);
    property Sorted: Boolean read GetSorted write SetSorted;

    function GetCaseSensitive: Boolean;
    procedure SetCaseSensitive(const Value: Boolean);
    property CaseSensitive: Boolean read GetCaseSensitive write SetCaseSensitive;

    function GetDuplicates: TDuplicates;
    procedure SetDuplicates(const Value: TDuplicates);
    property Duplicates: TDuplicates read GetDuplicates write SetDuplicates;
  public
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    class function NewInstance: TObject; override;
  end;

class function TStringListIntf.Create: IStringList;
begin
  Result := TInterfacedStringList.Create;
end;

function TInterfacedStringList.First: String;
begin
  Result := Strings[0];
end;

function TInterfacedStringList.Last: String;
begin
  Result := Strings[Count-1];
end;

function TInterfacedStringList.AddPair(const Name, Value: string): IStringList;
begin
  Add(Name + NameValueSeparator + Value);
  Result := Self;
end;

function TInterfacedStringList.GetDelimiter: Char;
begin
  Result := inherited Delimiter;
end;

procedure TInterfacedStringList.SetDelimiter(aChar: Char);
begin
  inherited Delimiter := aChar;
end;

function TInterfacedStringList.GetDelimitedText: String;
begin
  Result := inherited DelimitedText;
end;

procedure TInterfacedStringList.SetDelimitedText(aText: String);
begin
  inherited DelimitedText := aText;
end;

function TInterfacedStringList.GetValue(const Name: string): String;
begin
  Result := inherited Values[Name];
end;

procedure TInterfacedStringList.SetValue(const Name, Value: string);
begin
  inherited Values[Name] := Value;
end;

function TInterfacedStringList.GetSorted: Boolean;
begin
  Result := inherited Sorted;
end;

procedure TInterfacedStringList.SetSorted(Value: Boolean);
begin
  inherited Sorted := Value;
end;

function TInterfacedStringList.GetCaseSensitive: Boolean;
begin
  Result := inherited CaseSensitive;
end;

procedure TInterfacedStringList.SetCaseSensitive(const Value: Boolean);
begin
  inherited CaseSensitive := Value;
end;

function TInterfacedStringList.GetDuplicates: TDuplicates;
begin
  Result := inherited Duplicates;
end;

procedure TInterfacedStringList.SetDuplicates(const Value: TDuplicates);
begin
  inherited Duplicates := Value;
end;

procedure TInterfacedStringList.AddStrings(Strings: IStringList);
begin
  inherited AddStrings(TStrings(Strings));
end;

{procedure TInterfacedStringList.SetStrings(Source: IStringList);
begin
  inherited SetStrings(TStrings(Source));
end;}

function TInterfacedStringList.GetRefCount: Integer;
begin
  Result := FRefCount and not objDestroyingFlag;
end;

class procedure TInterfacedStringList.__MarkDestroying(const Obj);
var
  LRef: Integer;
begin
  repeat
    LRef := TInterfacedStringList(Obj).FRefCount;
  until AtomicCmpExchange(TInterfacedStringList(Obj).FRefCount, LRef or objDestroyingFlag, LRef) = LRef;
end;

procedure TInterfacedStringList.AfterConstruction;
begin
// Release the constructor's implicit refcount
  AtomicDecrement(FRefCount);
end;

procedure TInterfacedStringList.BeforeDestruction;
begin
  if RefCount <> 0 then
    System.Error(reInvalidPtr);
end;

// Set an implicit refcount so that refcounting during construction won't destroy the object.
class function TInterfacedStringList.NewInstance: TObject;
begin
  Result := inherited NewInstance;
  TInterfacedStringList(Result).FRefCount := 1;
end;

function TInterfacedStringList.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TInterfacedStringList._AddRef: Integer;
begin
  Result := AtomicIncrement(FRefCount);
end;

function TInterfacedStringList._Release: Integer;
begin
  Result := AtomicDecrement(FRefCount);
  if Result = 0 then
  begin
    // Mark the refcount field so that any refcounting during destruction doesn't infinitely recurse.
    __MarkDestroying(Self);
    Destroy;
  end;
end;

end.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值