gpt4 book ai didi

delphi - 如何将字段接口(interface)注入(inject)到对象中

转载 作者:行者123 更新时间:2023-12-03 15:57:59 25 4
gpt4 key购买 nike

我想给对象注入(inject)接口(interface)但是找不到属性[Inject]的问题

什么有效。

unit uStorage;

interface

uses
uStorageInterface;

type
TStorageService = class (TInterfacedObject, IStorageService)
private
FPath: String;
procedure SetPath(const Value: String);
function GetPath: String;
public
property Path: String read GetPath write SetPath;
end;

implementation

{ TStorageService }

function TStorageService.GetPath: String;
begin
Result:= FPath;
end;

procedure TStorageService.SetPath(const Value: String);
begin
FPath := Value;
end;
<小时/>
unit uStorageInterface;

interface

type
IStorageService = interface
['{F1B4C339-BE8E-4182-A191-95266160FA6E}']
procedure SetPath(const Value: String);
function GetPath: String;
property Path: String read GetPath write SetPath;
end;

IStorageObject = interface
['{7B97B659-EDF3-4892-AFAB-985487660372}']
end;

implementation

end.
<小时/>
unit uObjects;

interface

uses
Vcl.StdCtrls,
System.Classes,
uStorageInterface,
Spring.Container,
Spring.Services,
Spring.Container.Common;

type

TMyButton= class (TButton, IStorageObject)
private
FStorage: IStorageService;
function GetStorage: IStorageService;

protected
procedure DoExit; override;

public
constructor Create(AOwner: TComponent); override;
end;

implementation

{ TMyButton }
constructor TMyButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FStorage:= ServiceLocator.GetService<IStorageService>;
end;

procedure TMyButton.DoExit;
begin
inherited;
if assigned(FStorage) then
begin
self.Caption:= FStorage.Path;
end;
end;

function TMyButton.GetStorage: IStorageService;
begin
Result:= FStorage;
end;

end.
<小时/>
unit Unit2;

interface

uses
System.SysUtils, System.Classes,
Vcl.Dialogs;

type
TDataModule2 = class(TDataModule)
procedure DataModuleCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
DataModule2: TDataModule2;

implementation

uses
uStorage,
uObjects,
uStorageInterface,
Spring.Services,
Spring.Container;

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

procedure TDataModule2.DataModuleCreate(Sender: TObject);
begin
GlobalContainer.RegisterType<TStorageService>.Implements<IStorageService>.DelegateTo(
function: TStorageService
begin
Result := TStorageService.Create();
Result.Path:= 'MyButton';
end).AsSingleton;
GlobalContainer.Build;
end;
end.

在构造函数 TMyButton.Create(AOwner: TComponent) 中,我想用字段注入(inject)替换 ServiceLocator,但我找不到如何执行此操作。

一些例子,但它不起作用。我看不出问题所在。

unit uObjects;

interface

uses
Vcl.StdCtrls,
System.Classes,
uStorageInterface,
Spring.Container,
Spring.Services,
Spring.Container.Common;

type

TMyButton= class (TButton, IStorageObject)
private
[Inject]
FStorage: IStorageService;
function GetStorage: IStorageService;

protected
procedure DoExit; override;

public
constructor Create(AOwner: TComponent); override;
end;

implementation

{ TMyButton }
constructor TMyButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
//FStorage:= ServiceLocator.GetService<IStorageService>;
end;

procedure TMyButton.DoExit;
begin
inherited;
if assigned(FStorage) then
begin
self.Caption:= FStorage.Path;
end;
end;

function TMyButton.GetStorage: IStorageService;
begin
Result:= FStorage;
end;

end.
<小时/>
procedure TDataModule2.DataModuleCreate(Sender: TObject);
begin
GlobalContainer.RegisterType<TStorageService>.Implements<IStorageService>.DelegateTo(
function: TStorageService
begin
Result := TStorageService.Create();
Result.Path:= 'MyButton';
end).AsSingleton;

GlobalContainer.RegisterType<TMyButton>.Implements<IStorageObject>.InjectField('FStorage');
GlobalContainer.Build;
end;

当我在运行时创建 TMyButton 时,TMyButton 中的 FStorage 为空。当我使用 FStorage:= ServiceLocator.GetService; 时然后在构造函数中分配 FStorage。但我想使用注入(inject)而不是 ServiceLocator。如果可能的话。

最佳答案

首先注册TMyButton是错的。容器本身不会为 AOwner 填充 nil。这意味着它将回退到 TObject 构造函数,使按钮实例保持一半初始化状态。

要么使用子依赖解析器为 TComponent 构造函数执行此操作,要么以这种方式显式注册它。

GlobalContainer.RegisterType<TMyButton>.Implements<IStorageObject>
.DelegateTo(
function: TMyButton
begin
Result := TMyButton.Create(nil);
end)
.InjectField('FStorage');

现在注意!如果您在某处将其解析为 TMyButton,则容器不知道如何解析该问题,因为您将 IStorageObject 指定为服务类型。如果指定服务类型,除非显式定义,否则容器不会解析该类。然而,这里有一个小故障,因为容器在解析该类时会尝试再次注册该类。这会导致 TMyButton 的第二次注册,但未指定字段注入(inject)。我会解决这个问题。

在此之前,您可以通过添加 Implements<TMyButton> 来解决此问题到您的注册。

关于delphi - 如何将字段接口(interface)注入(inject)到对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30345602/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com