首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么.NET核心DI容器不注入ILogger?

为什么.NET核心DI容器不注入ILogger?
EN

Stack Overflow用户
提问于 2020-06-02 08:48:51
回答 2查看 5.5K关注 0票数 12

我正在尝试在基于C# Core2.1的.NET控制台应用程序中登录并运行。

我在DI声明中添加了以下代码:

代码语言:javascript
运行
复制
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”类型的服务。

代码语言:javascript
运行
复制
    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容器中公开服务吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-02 08:51:49

依赖注入系统不注册ILogger。相反,它注册了ILogger<T>。如果需要记录器的实例,则需要接受ILogger<MyService>

这背后的原因是,泛型参数用于构建记录器的类别名称--这是所有记录器都需要的。对于非通用的记录器,不一定有一个好的默认名称。如果您真的想要一个非通用的ILogger,您可以这样注册一个(请随意更改名称):

代码语言:javascript
运行
复制
services.AddSingleton(sp => sp.GetRequiredService<ILoggerFactory>().CreateLogger("DefaultLogger"));

或者,您可以在构造函数中接受一个ILoggerFactory,然后动态创建自己的记录器。

票数 14
EN

Stack Overflow用户

发布于 2020-06-02 09:05:28

为了使MS.DI能够完成从ILoggerILogger<T>的映射,其中T成为消费者,它必须支持基于上下文的注入。这意味着在使用MS.DI构建应用程序时,必须让类依赖于ILogger<T>

MS.DI缺乏此功能的原因有很多。我认为最重要的两个原因是:

  • MS.DI只实现了框架组件本身所需的特性。记住: MS.DI是为ASP.NET核心框架、组件及其第三方构建和设计的。更不用说成为一个成熟的DI容器了
  • MS.DI试图成为一个最低的公共分母 (LCD),它只支持所有其他DI容器也支持的特性,从而允许您用一个更成熟、功能更丰富的DI容器来替换这个内置容器。

我理解你的烦恼。看到MS.DI支持基于上下文的注入是很好的,因为您的应用程序组件依赖于ILogger是很有意义的,因为使您的代码更简单、更容易测试,并且不太容易出错。

不幸的是,由于MS.DI的设计和它的LCD哲学,它不太可能得到这样的功能。每次Microsoft添加行为时,都会开始与大多数DI容器的维护人员进行长时间而复杂的讨论,以了解如何以与所有其他库兼容的方式支持这些特性(我自己也曾参与过许多此类讨论)。这是一项艰巨的任务,在某些情况下,证明已经是不可能的。

相反,选择一个更成熟和功能更丰富的DI容器来包含这样的特性和许多其他特性是有意义的。例如,对于简单喷射器,我们附加集成用于注入ILogger。但是还有其他DI容器允许您注入ILogger

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62148204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档