如何在Spring4D中实现带有作用域的上下文?
我希望能够注册一个带作用域寿命的单例,其工作方式类似TSingletonPerThreadLifetimeManager,但在超出作用域时会被释放。
我想具备在一个作用域的上下文中,将某些对象视为单例。
在下面的示例中,Context 被 TTest 与 TSub 都使用。我希望它们都指向同一个实例,但彼此不知晓对方也在使用它。
type
TSub = class(TInterfacedObject, ISub)
public
constructor Create(Context: IContext);
end;
TTest = class(TInterfacedObject, ITest)
public
constructor Create(Context: IContext; Sub: ISub);
end;
Container.RegisterType<IContext,TContext>.AsScoped;
Container.RegisterType<ITest,TTest>.AsTransient;
Container.RegisterType<ISub,TSub>.AsTransient;
var Scope:=TScope.New;
try
var test:=Container.Resolve<ITest>();
test.execute;
finally
Scope:=nil;
end;
理想情况下,我不想在作用域内直接引用容器,而是处理传入的动态工厂,例如:
procedure DoInScope(TestFactory: Func<ITest>);
begin
var Scope:=TScope.New;
try
TestFactory().Execute;
finally
Scope:=nil;
end;
end;
我看过TSingletonPerThreadLifetimeManager,但无法弄清楚如何在作用域结束时释放引用。
另一种我能想到的选项是使用委托,例如:
Container.RegisterType<IContext,TContext>.DelegateTo(
function: IContext
begin
if TScope.InScope then
begin
if not TScope.Has<IContext> then
TScope.Add<IContext>(Container.Resolve<IContext>); // wont work as recursive
Result:=TScope.Get<IContext>;
end;
end
);
解决方案
没有带作用域寿命的生命周期,只有按解析创建实例的生命周期。
uses
Spring.Container;
type
ISub = interface
end;
ITest = interface
end;
IContext = interface
end;
TContext = class(TInterfacedObject, IContext)
public
constructor Create;
end;
TSub = class(TInterfacedObject, ISub)
private
fContext: IContext;
public
constructor Create(Context: IContext);
end;
TTest = class(TInterfacedObject, ITest)
private
fContext: IContext;
public
constructor Create(Context: IContext; Sub: ISub);
end;
constructor TContext.Create;
begin
Writeln('creating context');
end;
constructor TSub.Create(Context: IContext);
begin
Writeln('creating sub');
fContext := Context;
end;
constructor TTest.Create(Context: IContext; Sub: ISub);
begin
Writeln('creating test');
fContext := Context;
end;
begin
GlobalContainer.RegisterType<IContext,TContext>.PerResolve;
GlobalContainer.RegisterType<ITest,TTest>.AsTransient;
GlobalContainer.RegisterType<ISub,TSub>.AsTransient;
GlobalContainer.Build;
GlobalContainer.Resolve<ITest>();
end.
将输出如下:
creating context
creating sub
creating test
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。