为什么 .NET Core DI 容器不注入 ILogger? [英] Why does .NET Core DI container not inject ILogger?
问题描述
我正在尝试在基于 .NET Core 2.1 的 C# 控制台应用程序中进行登录和运行.
I am trying to get logging up and running in my C# console app based on .NET Core 2.1.
我在 DI 声明中添加了以下代码:
I added the following code to my DI declaration:
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
来注入服务,但出现以下错误:
I am trying to inject the service by using the Interface Microsoft.Extensions.Logging.ILogger
in the constructor of the services, but I am getting the following error:
未处理的异常:System.InvalidOperationException:在尝试激活MyService"时无法解析Microsoft.Extensions.Logging.ILogger"类型的服务.
Unhandled Exception: System.InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'MyService'.
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 吗?
Did I misunderstand something here? Shouldn't the AddLogging
method be enough to expose the Service in the DI Container?
推荐答案
依赖注入系统没有注册 ILogger
.相反,它注册 ILogger
.如果您需要记录器的实例,则需要接受 ILogger
.
The dependency injection system doesn't register ILogger
. Instead it registers ILogger<T>
. If you need an instance of a logger, you will need to accept ILogger<MyService>
.
这背后的原因是泛型参数用于构建记录器的类别名称——这是所有记录器都需要的.对于非通用记录器,不一定有一个好的默认名称.如果你真的想要一个非通用的ILogger
,你可以像这样注册一个(随意更改名称):
The reason behind this is that the generic argument is used to build the logger's category name--something which all loggers require. With a non-generic logger there's not necessarily a good default name. If you really want a non-generic ILogger
, you can register one like this (change the name as you please):
services.AddSingleton(sp => sp.GetRequiredService<ILoggerFactory>().CreateLogger("DefaultLogger"));
或者,您可以在构造函数中接受 ILoggerFactory
,然后即时创建自己的记录器.
Alternatively, you can accept an ILoggerFactory
in your constructor and then create your own logger on the fly.
这篇关于为什么 .NET Core DI 容器不注入 ILogger?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!