我用的是 Unity.Container
NuGet包5.11,我想注册一个开放通用类型,使每个具体类型都是一个单子。
背景:我正在一个老式的ASP.NET WebForms应用程序中工作。我在一个老式的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>
解决了,它就能正常工作--但是 第二 时候 ILogger<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版本5.11.7中,这个问题得到了解决。