SimpleInjector.ActivationException 由于 collection 生活方式
SimpleInjector.ActivationException due to collection lifestyle
我正在尝试将我的 DI 容器从 Unity 切换到 SimpleInjector,我在 collections 上遇到了一些困难。
我有两个 IExceptionLogWriter
的具体实现,我想注册为单例,所以我执行以下操作:
container.RegisterSingleton<RaygunExceptionLogWriter>();
container.RegisterSingleton<SqlExceptionLogWriter>();
现在我想用 collection 注册这两个,所以我这样做:
container
.RegisterCollection<IExceptionLogWriter>(
new[] {
typeof(RaygunExceptionLogWriter),
typeof(SqlExceptionLogWriter) });
现在,当我尝试 运行 应用程序时,出现以下错误:
Additional information: A lifestyle mismatch is encountered. ExceptionLogger (Singleton) depends on IExceptionLogWriter[] (Transient). Lifestyle mismatches can cause concurrency bugs in your application. Please see https://simpleinjector.org/dialm to understand this problem and how to solve it.
如果我正确理解错误,看起来我需要以某种方式将 IExceptionLogWriter[]
注册为单例,因为我将 RaygunExceptionLogWriter
和 SqlExceptionLogWriter
注册为单例。也许我很笨,但我一辈子都想不出该怎么做。
我试过这个:
container.RegisterSingleton<IExceptionLogWriter[]>();
那明显是坠机烧毁了
编辑 - 所有相关注册
container.RegisterSingleton<SqlConnectionFactory>(new SqlConnectionFactory(connectionString));
container.RegisterSingleton<IApplicationExceptionRepository, SqlApplicationExceptionRepository>();
container.RegisterSingleton<IErrorHandler, ErrorHandler>();
container.RegisterSingleton<IExceptionLogger, ExceptionLogger>();
container.RegisterSingleton<RaygunExceptionLogWriter>();
container.RegisterSingleton<SqlExceptionLogWriter>();
container
.RegisterCollection<IExceptionLogWriter>(
new[] {
typeof(RaygunExceptionLogWriter),
typeof(SqlExceptionLogWriter) });
以及相关的构造函数:
public SqlConnectionFactory(string connectionString)
public SqlApplicationExceptionRepository(SqlConnectionFactory connectionFactory)
public ErrorHandler(IExceptionLogger exceptionLogger)
public ExceptionLogger(IExceptionLogWriter[] exceptionLogWriters)
public RaygunExceptionLogWriter()
public SqlExceptionLogWriter(IApplicationExceptionRepository applicationExceptionRepository)
这里发生的事情是您的 ExceptionLogger
组件有一个类型为 IExceptionLogWriter[]
的构造函数参数(IExceptionLogWriter
的数组)。 Simple Injector 会自动为您解析数组,但 Simple Injector 进行的隐式注册是暂时的。这样做的原因是:
- 数组是引用列表。如果列表包含瞬态组件,则将数组作为单例注入将导致 Captive Dependencies.
- 数组是可变类型;每个人都可以更改数组的内容。使其成为单例可能会导致应用程序的不相关部分因数组更改而失败。
因此,出于安全原因,Simple Injector 使数组注册成为瞬态。这允许诊断系统启动并警告您它可能导致的任何依赖性。
解决方法很简单,您有两个选择:
- 使
ExceptionLogger
消费者瞬态,或
- 将
ExceptionLogger
的依赖性从 IExceptionLogger[]
更改为 IEnumerable<IExceptionLogger>
、IList<IExceptionLogger>
、ICollection<IExceptionLogger>
、IReadOnlyList<IExceptionLogger>
或 IReadOnlyCollection<IExceptionLogger>
.
对于这些集合抽象,Simple Injector 将注入一个集合:
- 无法从外部更改,并且
- 通过在每次迭代集合时根据其生活方式解析元素来防止俘虏依赖。
我正在尝试将我的 DI 容器从 Unity 切换到 SimpleInjector,我在 collections 上遇到了一些困难。
我有两个 IExceptionLogWriter
的具体实现,我想注册为单例,所以我执行以下操作:
container.RegisterSingleton<RaygunExceptionLogWriter>();
container.RegisterSingleton<SqlExceptionLogWriter>();
现在我想用 collection 注册这两个,所以我这样做:
container
.RegisterCollection<IExceptionLogWriter>(
new[] {
typeof(RaygunExceptionLogWriter),
typeof(SqlExceptionLogWriter) });
现在,当我尝试 运行 应用程序时,出现以下错误:
Additional information: A lifestyle mismatch is encountered. ExceptionLogger (Singleton) depends on IExceptionLogWriter[] (Transient). Lifestyle mismatches can cause concurrency bugs in your application. Please see https://simpleinjector.org/dialm to understand this problem and how to solve it.
如果我正确理解错误,看起来我需要以某种方式将 IExceptionLogWriter[]
注册为单例,因为我将 RaygunExceptionLogWriter
和 SqlExceptionLogWriter
注册为单例。也许我很笨,但我一辈子都想不出该怎么做。
我试过这个:
container.RegisterSingleton<IExceptionLogWriter[]>();
那明显是坠机烧毁了
编辑 - 所有相关注册
container.RegisterSingleton<SqlConnectionFactory>(new SqlConnectionFactory(connectionString));
container.RegisterSingleton<IApplicationExceptionRepository, SqlApplicationExceptionRepository>();
container.RegisterSingleton<IErrorHandler, ErrorHandler>();
container.RegisterSingleton<IExceptionLogger, ExceptionLogger>();
container.RegisterSingleton<RaygunExceptionLogWriter>();
container.RegisterSingleton<SqlExceptionLogWriter>();
container
.RegisterCollection<IExceptionLogWriter>(
new[] {
typeof(RaygunExceptionLogWriter),
typeof(SqlExceptionLogWriter) });
以及相关的构造函数:
public SqlConnectionFactory(string connectionString)
public SqlApplicationExceptionRepository(SqlConnectionFactory connectionFactory)
public ErrorHandler(IExceptionLogger exceptionLogger)
public ExceptionLogger(IExceptionLogWriter[] exceptionLogWriters)
public RaygunExceptionLogWriter()
public SqlExceptionLogWriter(IApplicationExceptionRepository applicationExceptionRepository)
这里发生的事情是您的 ExceptionLogger
组件有一个类型为 IExceptionLogWriter[]
的构造函数参数(IExceptionLogWriter
的数组)。 Simple Injector 会自动为您解析数组,但 Simple Injector 进行的隐式注册是暂时的。这样做的原因是:
- 数组是引用列表。如果列表包含瞬态组件,则将数组作为单例注入将导致 Captive Dependencies.
- 数组是可变类型;每个人都可以更改数组的内容。使其成为单例可能会导致应用程序的不相关部分因数组更改而失败。
因此,出于安全原因,Simple Injector 使数组注册成为瞬态。这允许诊断系统启动并警告您它可能导致的任何依赖性。
解决方法很简单,您有两个选择:
- 使
ExceptionLogger
消费者瞬态,或 - 将
ExceptionLogger
的依赖性从IExceptionLogger[]
更改为IEnumerable<IExceptionLogger>
、IList<IExceptionLogger>
、ICollection<IExceptionLogger>
、IReadOnlyList<IExceptionLogger>
或IReadOnlyCollection<IExceptionLogger>
.
对于这些集合抽象,Simple Injector 将注入一个集合:
- 无法从外部更改,并且
- 通过在每次迭代集合时根据其生活方式解析元素来防止俘虏依赖。