无法从 Microsoft.Extensions.Logging 解析 ILogger
Posted
技术标签:
【中文标题】无法从 Microsoft.Extensions.Logging 解析 ILogger【英文标题】:Unable to resolve ILogger from Microsoft.Extensions.Logging 【发布时间】:2019-03-26 02:13:54 【问题描述】:我已经像这样配置了我的控制台应用程序的Main
var services = new ServiceCollection()
.AddLogging(logging => logging.AddConsole())
.BuildServiceProvider();
然后我尝试在另一个类中使用它
private readonly ILogger _logger;
public MyClass(ILogger logger)
_logger = logger;
public void MyFunc()
_logger.Log(LogLevel.Error, "My Message");
System.InvalidOperationException: '无法解析服务类型 'Microsoft.Extensions.Logging.ILogger'
我已经尝试了here 的解决方案,但它对我不起作用。
编辑 根据下面 Yaakov 的评论和this Github comment,我可以通过这样做正确解决它
public MyClass(ILogger<MyClass> logger)
_logger = logger;
我本来希望在最初的 BuildServiceProvider
中有这个,但看起来我每次想使用记录器(或创建我自己的 ILogger)时都必须重复这个。
【问题讨论】:
那么您注册服务集合的部分在哪里? @EmrahSüngü 我不认为我是单独做的。在..AddLogging(logging => logging.AddConsole())
之后,我在该链中还有其他解析器,例如正确解析的.AddScoped<IMyInterface, MyMethod>()
。
如果您尝试解析 ILogger<MyClass>
是否有效?
@yaakov 是的,确实如此。但是有没有其他方法可以注册,这样我就不必每次都做public MyClass(ILogger<MyClass> logger)
?
我不知道。我相信它的设计方式是让 DI 还添加有关从何处记录数据的信息。
【参考方案1】:
ILogger
不再默认注册,但ILogger<T>
是。如果您仍想使用 ILogger,您可以使用以下代码手动注册(Startup.cs
):
public void ConfigureServices(IServiceCollection services)
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<AnyClass>>();
services.AddSingleton(typeof(ILogger), logger);
...
AnyClass
可以是通用的,例如:
public class ApplicationLogs
所以:
public void ConfigureServices(IServiceCollection services)
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<ApplicationLog>>();
services.AddSingleton(typeof(ILogger), logger);
...
ILogger
现在将通过构造函数注入进行解析。
【讨论】:
这被认为是不好的做法(从 ConfigureServices 构建您的服务提供者)。这样,您的所有单例服务都会被实例化两次。 @MathiasLykkegaardLorenzen 包括或指明首选实现会很有帮助。 很确定你应该注册一个瞬态,在运行时解析ILogger<ApplicationLog>
创建中间服务提供者有点阴暗,但这可能是避免它的解决方案:***.com/a/70610564/646942【参考方案2】:
我假设您正在使用 .net 核心 Web 应用程序的默认模板。 在您的 Startup.cs 中,您应该有这样的方法↓↓↓↓↓↓↓
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
services.Configure<CookiePolicyOptions>(options =>
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//Do the service register here and extra stuff you want
services.AddLogging(config =>
config.AddDebug();
config.AddConsole();
//etc
);
编辑:我为你编写了一个简单的程序来展示它是如何工作的
public class MyClass
private readonly ILogger<MyClass> _logger;
public MyClass(ILogger<MyClass> logger)
_logger = logger;
public void MyFunc()
_logger.Log(LogLevel.Error, "My Message");
public class Program
public static void Main(string[] args)
var services = new ServiceCollection().AddLogging(logging => logging.AddConsole());
services.AddSingleton<MyClass>();//Singleton or transient?!
var s = services.BuildServiceProvider();
var myclass = s.GetService<MyClass>();
编辑:程序的输出:
【讨论】:
这是一个控制台应用程序,就像问题所说的那样。您在services.AddLogging
中显示的内容与我在问题中的内容有何不同?
让我再问一次。var services = new ServiceCollection()
你创建了一个新的服务集合对吗?你在哪里注册到你的应用程序?什么解决了依赖关系?谁创建了 MyClass 的新实例
好吧,伙计,既然你拒绝了帮助 :) 除了建议阅读 DI 之外,我无能为力了
抱歉,它应该是这样工作还是应该不工作?
这显示了它应该如何工作,正如您在示例代码中看到的那样,它可以工作并且 logger 是一个 ConsoleLogger。我不明白为什么我们不能互相理解:(【参考方案3】:
在 .NET Core 中,ILogger<T>
会自动为您注册。由于ILogger<T>
继承自ILogger
,您可以从IServiceProvider
请求ILogger<T>
的实例。
例如:
services.AddSingleton<ILogger>(svc => svc.GetRequiredService<ILogger<MyClassType>>());
请注意,只要您有一个非泛型 ILogger
构造函数参数,这将返回一个 ILogger<MyClassType>
,因此如果您需要多个参数,请考虑使用 AddSingleton
专门为该实例创建它(或瞬态/或作用域) implementationFactory 覆盖。
【讨论】:
【参考方案4】:正如评论中所述,接受的答案存在BuildServiceProvider
不应在ConfigureServices
中使用的问题,因为它会创建每个单例(实际上是整个 DI 容器)的另一个副本。这是避免该问题的替代单线。在ConfigureServices
中添加一行
services.AddSingleton<Microsoft.Extensions.Logging.ILogger>(provider =>
provider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<AnyClass>>());
AnyClass
可以是任何类,如接受的答案中所述。这会将ILogger
的分辨率重定向到ILogger<AnyClass>
的分辨率。
与公认的答案一样,这个问题的缺点是 Serilog 的 SourceContext
将被设置为 AnyClass
。因此,如果您的 Serilog 配置包含一个包含 SourceContext
的 outputTemplate
,您的日志将显示 AnyClass
而不是包含日志记录语句的类。
【讨论】:
这是一个很好的方法。时尚干净。【参考方案5】:此答案不一定适用于 .net Core 或海报使用的任何依赖注入。我遇到了这个寻找一种在 asp.net 表单 Web 应用程序中使用 Autofac 修复此错误的方法。日志没有“默认注册”的答案导致我将其添加到我的注册中:
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
现在它对我有用。这是我第二次搜索这个答案并最终来到这里,我忘记了我第一次是如何修复它的。所以我想我会发布我的答案。
【讨论】:
【参考方案6】:对于 .NET Core 3.1,请务必包含
Microsoft.Extensions.Logging
通过调用打包和配置日志记录
IServiceCollection services = new ServiceCollection();
services.AddLogging();
【讨论】:
这是我一直在寻找的真正答案... 【参考方案7】:根据@Barry 回答above 了解如何为Microsoft.Extensions.DependencyInjection
注册通用日志提供程序:
var services = new ServiceCollection()
.AddLogging(logging => logging.AddConsole())
.BuildServiceProvider();
services.AddSingleton<ILoggerFactory, LoggerFactory>()
services.Add(ServiceDescriptor.Describe(typeof(ILogger<>),typeof(Logger<>),ServiceLifetime.Scoped))
【讨论】:
【参考方案8】:我在尝试使用 ILogger
时使用的方法(因为它不再被注入),例如注入 ILoggerFactory
,然后当您的代码需要特定的记录器时(比如说它的某个自定义工厂,您是 @ 987654323@ing up, LoggerFactory.CreateLogger("Logger Name")
- 下面
但对于你的情况,看起来你想要一个ILogger<MyClass>
public class MyClass
private readonly ILoggerFactory _loggerFactory;
public MyClass(ILoggerFactory loggerFactory)
_loggerFactory = _loggerFactory;
public void MyFunc()
new MyNewThatsASpecialCase(_loggerFactory.CreateLogger("MyNewThatsASpecialCase"));
【讨论】:
这对我有用,因为 LoggerFactory 是我请求服务时唯一可用的实例,而不是类记录器。【参考方案9】:这就是我让 DI 为 ILogger 工作的原因。
对于 .NET Core,请参阅: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0
具体来说:
.ConfigureLogging(logging =>
logging.ClearProviders();
logging.AddConsole();
)
参考:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
logging.ClearProviders();
logging.AddConsole();
)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.UseStartup<Startup>();
);
【讨论】:
净 6.0 docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/…【参考方案10】:对于使用 NLog 遇到此错误的任何人,我发现我在依赖注入中犯了以下错误:
private readonly ILogger _logger;
public ErrorController(ILogger ilogger)
_logger = ilogger;
According to the documentation,在 .Net 5 中,您需要将 Controller 本身的类型添加到记录器以避免此问题。这样的依赖注入修复了错误:
private readonly ILogger<ErrorController> _logger;
public ErrorController(ILogger<ErrorController> ilogger)
_logger = ilogger;
进行上述更改后,这解决了我的问题。不要在这里尝试任何解决方案!这只会让你陷入困境。
希望这对将来的任何人都有帮助!
【讨论】:
【参考方案11】:接受的答案(由@sam-shiles 提供)朝着正确的方向发展。我不喜欢它需要构建一个中间服务提供者,并且可能也不需要注册单例实例。
所以,我建议注册一个工厂,而不是使用ILoggerFactory
。创建一个空类(如AnyClass
也不需要)。
...
services.AddTransient(provider =>
var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
const string categoryName = "Any";
return loggerFactory.CreateLogger(categoryName);
);
...
【讨论】:
以上是关于无法从 Microsoft.Extensions.Logging 解析 ILogger的主要内容,如果未能解决你的问题,请参考以下文章
命名空间Microsoft.Extensions中不存在缓存
无法使用 COM 加载文件或程序集“Microsoft.Extensions.DependencyInjection.Abstractions”
无法加载文件或程序集 Microsoft.Extensions.DependencyInjection.Abstractions,版本 = 1.1.0.0
无法解析类型“Microsoft.Extensions.Logging.ILogger`1[WebApplication1.Startup]”的服务
无法在 Azure Functions 中加载文件或程序集“Microsoft.Extensions.Configuration.Abstractions,版本=5.0.0.0
Azure 函数 5 和 EF Core 5 无法加载文件或程序集 > Microsoft.Extensions.DependencyInjection.Abstractions