You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确创建Spring4D IList<T>派生类型并扩展其功能?

关于Spring4D中自定义集合的规范实现与实例创建

一、更规范的IList扩展方式

你的实现方向是正确的——通过自定义接口继承IList<TDenonInput>扩展功能,再用实现类继承Spring4D的TList<TDenonInput>复用基础集合逻辑。这里可以优化几点:

  • 确保自定义接口的GUID唯一(你已完成),这是Delphi接口的必要要求。
  • 若LockedAdd和LockedClear是线程安全操作,可直接利用Spring4D内置的线程安全集合特性,无需手动实现锁逻辑。
  • 查找方法(GetInputByName/GetInputByRename)可借助Spring4D的LINQ扩展简化代码,提升可读性。

二、更合理的实例创建方式

Spring4D的TCollections.CreateList<T>用于创建框架原生的IList<T>实现,但对于你自定义的IDenonInputList,直接构造TDenonInputList完全合法。如果想贴合Spring4D的工厂模式风格,可给自定义集合添加静态创建方法,示例如下:

优化后的完整代码示例

{Using Spring4D.Collections; Spring4D.Collections.Lists; Spring4D.Core.Linq}

// 自定义扩展接口
IDenonInputList = interface(IList<TDenonInput>)
  ['{2201FB6B-1B9C-4FEE-9614-EFF2A7D35957}']
  function GetInputByName(const Name: string): TDenonInput;
  function GetInputByRename(const Name: string): TDenonInput;
  procedure LockedAdd(ADenonInput: TDenonInput);
  procedure LockedClear;
  property Names[const Name: string]: TDenonInput read GetInputByName;
  property Renames[const Name: string]: TDenonInput read GetInputByRename;
end;

// 实现类
TDenonInputList = class(TList<TDenonInput>, IDenonInputList)
private
  function GetInputByName(const Name: string): TDenonInput;
  function GetInputByRename(const Name: string): TDenonInput;
  procedure LockedAdd(ADenonInput: TDenonInput);
  procedure LockedClear;
public
  // 静态创建方法,贴合Spring4D工厂风格
  class function Create: IDenonInputList; static;
end;

{ TDenonInputList }

class function TDenonInputList.Create: IDenonInputList;
begin
  Result := inherited Create;
end;

function TDenonInputList.GetInputByName(const Name: string): TDenonInput;
begin
  // 利用Spring4D LINQ简化查找逻辑
  Result := Self.FirstOrDefault(function(const Input: TDenonInput): Boolean
    begin
      Result := Input.Name.Equals(Name);
    end);
end;

function TDenonInputList.GetInputByRename(const Name: string): TDenonInput;
begin
  Result := Self.FirstOrDefault(function(const Input: TDenonInput): Boolean
    begin
      Result := Input.Rename.Equals(Name);
    end);
end;

procedure TDenonInputList.LockedAdd(ADenonInput: TDenonInput);
begin
  // 线程安全实现示例,若无需线程安全可直接调用Add
  TMonitor.Enter(Self);
  try
    Add(ADenonInput);
  finally
    TMonitor.Exit(Self);
  end;
end;

procedure TDenonInputList.LockedClear;
begin
  TMonitor.Enter(Self);
  try
    Clear;
  finally
    TMonitor.Exit(Self);
  end;
end;

实例创建的两种方式

  1. 直接构造(简单直接):
var
  InputList: IDenonInputList;
begin
  InputList := TDenonInputList.Create;
  // ...后续操作
end;
  1. 使用静态工厂方法(贴合Spring4D风格):
var
  InputList: IDenonInputList;
begin
  InputList := TDenonInputList.Create;
  // 静态方法调用,与框架TCollections的使用风格一致
end;

额外轻量化方案

如果你的集合仅需添加查询类功能,无需特殊内部逻辑,可使用扩展方法替代自定义接口,无需创建新集合类型:

unit DenonInput.Extensions;

interface

uses
  Spring4D.Collections, DenonInput.Types;

type
  TDenonInputListExtensions = class
  public
    class function GetInputByName(const List: IList<TDenonInput>; const Name: string): TDenonInput; static;
    class function GetInputByRename(const List: IList<TDenonInput>; const Name: string): TDenonInput; static;
  end;

implementation

uses
  Spring4D.Core.Linq;

{ TDenonInputListExtensions }

class function TDenonInputListExtensions.GetInputByName(const List: IList<TDenonInput>; const Name: string): TDenonInput;
begin
  Result := List.FirstOrDefault(function(const Input: TDenonInput): Boolean
    begin
      Result := Input.Name.Equals(Name);
    end);
end;

class function TDenonInputListExtensions.GetInputByRename(const List: IList<TDenonInput>; const Name: string): TDenonInput;
begin
  Result := List.FirstOrDefault(function(const Input: TDenonInput): Boolean
    begin
      Result := Input.Rename.Equals(Name);
    end);
end;

end.

使用时直接调用:InputList.GetInputByName('Test')(需在uses中引入扩展单元),这种方式更简洁高效。


内容的提问来源于stack exchange,提问作者Greg Dawson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:05:14