如何正确创建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;
实例创建的两种方式
- 直接构造(简单直接):
var InputList: IDenonInputList; begin InputList := TDenonInputList.Create; // ...后续操作 end;
- 使用静态工厂方法(贴合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
相关产品推荐
相关产品推荐

