[英]Serilog DI in ASP.NET Core, which ILogger interface to inject?
[英]Why does .NET Core DI container not inject ILogger?
我正在尝试在基于 .NET Core 2.1 的 C# 控制台应用程序中登录并运行。
我将以下代码添加到我的 DI 声明中:
var sc = new ServiceCollection();
sc.AddLogging(builder =>
{
builder.AddFilter("Microsoft", LogLevel.Warning);
builder.AddFilter("System", LogLevel.Warning);
builder.AddFilter("Program", LogLevel.Warning);
builder.AddConsole();
builder.AddEventLog();
});
我正在尝试通过在服务的构造函数中使用接口Microsoft.Extensions.Logging.ILogger
来注入服务,但出现以下错误:
未处理的异常:System.InvalidOperationException:尝试激活“MyService”时无法解析“Microsoft.Extensions.Logging.ILogger”类型的服务。
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Program.Main(String[] args) in Program.cs:line 27
我在这里误解了什么吗? AddLogging
方法不应该足以在 DI 容器中公开 Service 吗?
依赖注入系统不注册ILogger
。 相反,它注册ILogger<T>
。 如果您需要记录器的实例,则需要接受ILogger<MyService>
。
这背后的原因是通用参数用于构建记录器的类别名称——所有记录器都需要的东西。 对于非通用记录器,不一定有一个好的默认名称。 如果您真的想要一个非通用ILogger
,您可以像这样注册一个(随意更改名称):
services.AddSingleton(sp => sp.GetRequiredService<ILoggerFactory>().CreateLogger("DefaultLogger"));
或者,您可以在构造函数中接受ILoggerFactory
,然后动态创建自己的记录器。
为了使 MS.DI 能够执行从ILogger
到ILogger<T>
的映射,其中T
成为使用者,它必须支持基于上下文的注入。 这意味着在使用 MS.DI 构建应用程序时,您必须让您的类依赖于ILogger<T>
。
MS.DI 缺少此功能的原因有很多。 我认为最重要的两个原因是:
我理解你的烦恼。 很高兴看到 MS.DI 支持基于上下文的注入,因为依赖ILogger
而不是应用程序组件非常有意义,因为这使您的代码更简单、更易于测试并且不易出错。
不幸的是,由于 MS.DI 的设计和 LCD 理念,它不太可能获得这样的功能。 每次 Microsoft 添加行为时,都会与大多数 DI 容器的维护者展开漫长而复杂的讨论,以了解如何以与所有其他库兼容的方式支持此类功能(我自己也参与了许多此类讨论) . 这是一项艰巨的任务,并且在某些情况下已被证明是不可能的。
相反,select 是一个更成熟、功能更丰富的 DI 容器,它包含这些功能以及许多其他功能。 例如,对于Simple Injector ,我们添加了用于注入ILogger
的集成。 但是还有其他 DI 容器允许您注入ILogger
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.