gpt4 book ai didi

c# - CaSTLe Windsor 使用带有 LifestyleTransient 的工厂方法

转载 作者:太空宇宙 更新时间:2023-11-03 12:23:48 24 4
gpt4 key购买 nike

考虑到 caSTLe windsor 3.4.0 中的以下实现:

public class ExampleInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<FailoverDatabaseConnectionExecutor>()
.ImplementedBy<FailoverDatabaseConnectionExecutor>()
.LifestyleTransient());

container.Register(Component.For<DatabaseConnectionExecutor>()
.ImplementedBy<DatabaseConnectionExecutor>()
.LifestyleTransient());

container.Register(Component.For<IDatabaseConnectionExecutor>()
UsingFactoryMethod(CreateDatabaseConnectionExecutor)
.LifestyleTransient()
.IsDefault());
}

private static IDatabaseConnectionExecutor CreateDatabaseConnectionExecutor(IKernel kernel)
{
var configurationRepository = kernel.Resolve<IConfigurationRepository>();

return configurationRepository.GetSetting(ConfigurationSettings.DatabaseFailoverEnabled, () => false)
? (IDatabaseConnectionExecutor)kernel.Resolve<FailoverDatabaseConnectionExecutor>()
: kernel.Resolve<DatabaseConnectionExecutor>();
}
}

框架返回以下异常:

Instance FailoverDatabaseConnectionExecutor of component Late bound IDatabaseConnectionExecutor is already being tracked. The factory method providing instances of the component is reusing instances, but the lifestyle of the component is Transient which requires new instance each time. In most cases it is advised for the factory method not to be handling reuse of the instances, but to chose a lifestyle that does that appropriately. Alternatively, if you do not wish for Windsor to track the objects coming from the factory change your regustration to '.UsingFactoryMethod(yourFactory, managedExternally: true)'

这会导致依赖链无法解析,并且我们的 Controller 上的属性注入(inject)会出现空值。

我们正在努力实现的是根据配置值 ConfigurationSettings.DatabaseFailoverEnabled 开启分辨率。我们希望这在工厂和底层解析类型上以 transient 方式发生。

从错误来看,这似乎是不可能的,我们的问题是我们如何实现工厂风格的实现,同时仍然在 FailoverDatabaseConnectionExecutorDatabaseConnectionExecutor 上保持短暂的生命周期

编辑:

在花了一些时间进一步调查之后,它似乎是一个与我的依赖链中的对象之一相关的问题。当其中一个对象实现 IDisposable 时,与 UsingFactoryMethod 结合使用时会发生此错误。

考虑以下(简化的)示例:

public class ServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ISomeConnectionService>()
.ImplementedBy<SomeConnectionService>()
.LifestyleTransient()
.IsDefault());

container.Register(
Component.For<FailoverDatabaseConnectionExecutor>()
.ImplementedBy<FailoverDatabaseConnectionExecutor>()
.LifestyleTransient());

container.Register(Component.For<IDatabaseConnectionExecutor>()
.UsingFactoryMethod(CreateDatabaseConnectionExecutor)
.LifestyleTransient()
.IsDefault());
}

private static IDatabaseConnectionExecutor CreateDatabaseConnectionExecutor(IKernel kernel)
{
return kernel.Resolve<FailoverDatabaseConnectionExecutor>();
}
}

public interface IDatabaseConnectionExecutor
{
}

public class SomeConnectionService : ISomeConnectionService, IDisposable
{
public SomeConnectionService()
{

}

public void Dispose()
{
}
}

public interface ISomeConnectionService
{
}

public class FailoverDatabaseConnectionExecutor : IDatabaseConnectionExecutor
{
private readonly ISomeConnectionService _someConnectionService;

public FailoverDatabaseConnectionExecutor(ISomeConnectionService someConnectionService)
{
_someConnectionService = someConnectionService;
}
}

从 SomeConnectionService 中删除 IDisposable 将正确注入(inject)依赖链。

有谁知道温莎城堡为什么会这样?

最佳答案

这里的问题是 .UsingFactoryMethod() 返回一个已经注册的组件,然后尝试再次注册它。

您可以尝试将 .Named() 添加到您的第一次和第二次注册中。

 container.Register(Component.For<IDatabaseConnectionExecutor>()
.ImplementedBy<FailoverDatabaseConnectionExecutor>()
.Named('FailoverExecutor')
.LifestyleTransient());

container.Register(Component.For<IDatabaseConnectionExecutor>()
.ImplementedBy<DatabaseConnectionExecutor>()
.Named('NormalExecutor')
.LifestyleTransient());

container.Register(Component.For<IDatabaseConnectionExecutor>()
UsingFactoryMethod(CreateDatabaseConnectionExecutor)
.LifestyleTransient()
.IsDefault());

然后在您的工厂方法中使用该名称解析组件。

 return configurationRepository.GetSetting(ConfigurationSettings.DatabaseFailoverEnabled, () => false)
? kernel.Resolve<IDatabaseConnectionExecutor>("FailoverExecutor")
: kernel.Resolve<IDatabaseConnectionExecutor>("NormalExecutor");

关于c# - CaSTLe Windsor 使用带有 LifestyleTransient 的工厂方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46075494/

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