首页 > 解决方案 > 使用开放通用单例注册时,“ContainerControlledLifetimeManager 的值只能设置一次”

问题描述

我正在使用Unity.ContainerNuGet 包 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

标签: unity-container

解决方案


现在在最新的统一版本 5.11.7 中修复了这个问题


推荐阅读