unity-container - 使用开放通用单例注册时,“ContainerControlledLifetimeManager 的值只能设置一次”
问题描述
我正在使用Unity.Container
NuGet 包 5.11,我想注册一个开放通用类型,以便每个具体类型都是单例。
背景:我在一个老式的 ASP.NET WebForms 应用程序中工作,我做了一个粗略的重新实现,Microsoft.Extensions.Logging
如下所示:
// `ILogger` is implemented elsewhere. Specifically I wrote an implementation using Serilog.
public interface ILogger
{
void Log( LogLevel level, String messageTemplate, params Object[] args );
}
// Unlike `ILogger`, this `ILogger<TSourceContext>` is not implemented by the code elsewhere (that uses Serilog, described above).
// Instead, it's only implemented by the internal class below:
public interface ILogger<TSourceContext> : ILogger
{
}
internal class LoggerWithSourceContext<TSourceContext> : ILogger<TSourceContext>
{
private readonly ILogger realLogger;
internal LoggerWithSourceContext( ILoggerFactory factory )
{
if( factory == null ) throw new ArgumentNullException(nameof(factory));
this.realLogger = factory.CreateLogger( sourceContext: typeof(TSourceContext).FullName );
}
public void Log( LogLevel level, String messageTemplate, params Object[] args )
{
this.realLogger.Log( level, messageTemplate, args );
}
}
// This is implemented elsewhere in my Serilog code.
public interface ILoggerFactory
{
ILogger CreateLogger( String sourceContext );
}
这是在我的根 Unity 容器中注册的,如下所示:
IUnityContainer rootContainer = ...
rootContainer
.RegisterSingleton<ILoggerFactory,MySerilogLoggerFactory>()
.RegisterSingleton( from: typeof(ILogger<>), to: typeof(LoggerWithSourceContext<>);
使用它时,第一次ILogger<T>
解决 an 时它工作正常 - 但是第二次解决 anILogger<T>
时失败并出现以下错误:
InvalidOperationException
ContainerControlledLifetimeManager 只能设置一次
我可以通过使用 将注册从 Singleton 更改为 Transient 注册来解决它RegisterType
,但我希望它使用 Singleton 注册来减轻内存或资源泄漏的风险:
IUnityContainer rootContainer = ...
rootContainer
.RegisterSingleton<ILoggerFactory,MySerilogLoggerFactory>()
.RegisterType( from: typeof(ILogger<>), to: typeof(LoggerWithSourceContext<>);
完整的堆栈跟踪:
ContainerControlledLifetimeManager can only be set once
-2146233079
System.InvalidOperationException
at Unity.Lifetime.ContainerControlledLifetimeManager.<>c.<SetValue>b__7_0(Object o, ILifetimeContainer c) in C:\projects\unity\Abstractions\src\Lifetime\Managers\ContainerControlledLifetimeManager.cs:line 70
at Unity.Lifetime.ContainerControlledLifetimeManager.SetValue(Object newValue, ILifetimeContainer container) in C:\projects\unity\Abstractions\src\Lifetime\Managers\ContainerControlledLifetimeManager.cs:line 70
at Unity.Strategies.LifetimeStrategy.PostBuildUp(BuilderContext& context) in C:\projects\unity\Container\src\Strategies\LifetimeStrategy.cs:line 86
at Unity.UnityContainer.<>c.<.ctor>b__41_3(BuilderStrategy[] chain, BuilderContext& context) in C:\projects\unity\Container\src\UnityContainer.Resolution.cs:line 431
at Unity.Builder.BuilderContext.Resolve(Type type, String name, InternalRegistration registration) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 177
at Unity.Builder.BuilderContext.Resolve(Type type, String name) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 67
at Unity.Builder.BuilderContext.Resolve(ParameterInfo parameter, Object value) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 217
at Unity.Processors.ConstructorProcessor.<>c__DisplayClass16_0.<GetResolverDelegate>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Constructor\ConstructorResolution.cs:line 77
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context) in C:\projects\unity\Container\src\Strategies\BuildPlanStrategy.cs:line 88
at Unity.UnityContainer.<>c.<.ctor>b__41_2(BuilderContext& context) in C:\projects\unity\Container\src\UnityContainer.Resolution.cs:line 363
at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type, String name, ResolverOverride[] overrides) in C:\projects\unity\Container\src\UnityContainer.IUnityContainer.cs:line 244
解决方案
现在在最新的统一版本 5.11.7 中修复了这个问题
推荐阅读
- jquery - 如果另一个 div 的 display 属性从 none 更改为 block,如何将一个 div 的 display 属性更改为 none?
- sql - 从 oracle 中的嵌套目录创建外部表
- nested - 嵌套模型不收敛
- deep-learning - 使用 LSTM 预测未来 6 个月的销售情况
- environment-variables - 在运行本地开发服务器时,在 UI 中设置的 Netlify 环境变量被注入为未定义
- php - Laravel Scout 不会导入记录 - Laravel 8
- python - p_mask=p_mask[span_idx].tolist(),AttributeError: - 'list' 对象没有属性 'tolist'
- c++ - 在 C++ 中查找最大数字
- javascript - MongoDB:从结果中返回动态字段
- amazon-web-services - 如何启动在 k8s 中的几个小型实例节点上运行的 pod?