Delphi接口依赖注入容器实现补全:Get<I>方法疑问
问题:Delphi基于接口的依赖注入容器Get方法实现疑问
我正在实现一个Delphi中基于接口的简易依赖注入容器,仅从YouTube课程中学到了方法签名,不清楚具体实现细节。目前大部分代码已完成,但核心方法function Get<I: IInterface>: I;的实现有疑问,不知道如何从字典中获取对应的TFunc<IInterface>并转换为指定返回类型I。
完整容器代码
unit uContainerDefault; interface uses System.TypInfo, System.SysUtils, System.Generics.Collections; type TGetter = TFunc<IInterface>; TContainer = class strict private FRecords: TDictionary<PTypeInfo, TGetter>; class var FDefault: TContainer; class function GetDefault: TContainer; static; public class constructor Create; class destructor Destroy; constructor Create; destructor Destroy; override; procedure Register<I: IInterface>(const pGetter: TGetter); function Get<I: IInterface>: I; class property Default: TContainer read GetDefault; end; implementation { TContainer } class constructor TContainer.Create; begin FDefault := TContainer.Create; end; constructor TContainer.Create; begin FRecords := TDictionary<PTypeInfo, TGetter>.Create; end; destructor TContainer.Destroy; begin FRecords.Free; inherited; end; class destructor TContainer.Destroy; begin FDefault.Free; end; function TContainer.Get<I>: I; begin {通过这段代码,我可以从字典中获取能返回接口的"TFunc<IInterface>",但我不知道是否应该用它来生成返回结果。} FRecords.Items[TypeInfo(I)]; end; class function TContainer.GetDefault: TContainer; begin Result := FDefault; end; procedure TContainer.Register<I>(const pGetter: TGetter); begin FRecords.Add(TypeInfo(I), pGetter); end; end.
注册示例(TProduct类初始化代码)
initialization TContainer.Default.Register<IProduct>( function: IInterface begin Result := TProduct.Create; end);
Get方法调用示例(窗体中操作Product实体)
begin TContainer.Default.Get<IProduct>.GetProduct; end;
待实现的Get方法代码
function TContainer.Get<I>: I; begin {通过这段代码,我可以从字典中获取能返回接口的"TFunc<IInterface>",但我不知道是否应该用它来生成返回结果。} FRecords.Items[TypeInfo(I)]; end;
解决方案
你需要取出字典中注册的TGetter并执行,将返回的IInterface实例转换为泛型参数指定的接口类型I,同时处理类型不匹配或未注册的情况。以下是完整的实现代码:
function TContainer.Get<I>: I; var LGetter: TGetter; LIntf: IInterface; begin // 尝试从字典中获取对应接口的Getter if not FRecords.TryGetValue(TypeInfo(I), LGetter) then raise Exception.CreateFmt('接口 %s 未注册', [GetTypeName(TypeInfo(I))]); // 执行Getter获取基础接口实例 LIntf := LGetter(); // 将基础接口转换为目标类型,同时验证兼容性 if not Supports(LIntf, I, Result) then raise Exception.CreateFmt('注册的Getter未返回 %s 类型的实例', [GetTypeName(TypeInfo(I))]); end;
代码说明
- 使用
TryGetValue替代直接访问Items,避免键不存在时抛出的默认异常,可根据需求调整错误处理(比如返回nil或自定义异常) - 执行
LGetter()获取IInterface类型的实例 - 通过
Supports函数完成类型转换,同时验证实例是否确实实现了目标接口I,确保类型安全
内容的提问来源于stack exchange,提问作者Rafael
相关产品推荐
相关产品推荐

