【发布时间】:2018-02-14 23:03:47
【问题描述】:
考虑在城堡温莎 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 IDatabaseConnectionExecutor 已被跟踪。工厂 提供组件实例的方法是重用实例,但是 组件的生活方式是瞬态的,这需要新的 每次的实例。在大多数情况下,建议使用工厂方法 不是处理实例的重用,而是选择一种生活方式 这样做是适当的。或者,如果您不希望 温莎追踪来自工厂的物体改变你的 注册到 '.UsingFactoryMethod(yourFactory, managedExternally: 真的)'
这会导致依赖链无法解析,并且我们的控制器上的属性注入为空值。
我们试图实现的是基于配置值ConfigurationSettings.DatabaseFailoverEnabled 的分辨率切换。我们希望这在工厂和底层解析类型上都以瞬时方式发生。
从错误看来这似乎是不可能的,我们的问题是我们如何实现工厂风格的实现,同时仍然在 FailoverDatabaseConnectionExecutor 和 DatabaseConnectionExecutor 上保持瞬态生命周期
编辑:
在花了一些时间进一步调查之后,这似乎是与我的依赖链中的一个对象相关的问题。当其中一个对象实现 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 将正确注入依赖链。
有人知道温莎城堡为什么会这样吗?
【问题讨论】:
-
请在从工厂方法返回之前尝试 Release() 配置存储库。使用 Castle 时,您应该养成为您 Resolve() 的所有内容显式调用 Release() 的习惯。
标签: c# .net inversion-of-control castle-windsor ioc-container