我已经这样配置了控制台应用程序的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)时,都必须重复此操作。
答案 0 :(得分:10)
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现在将通过构造函数注入来解析
答案 1 :(得分: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 配置包含一个包含 outputTemplate
的 {SourceContext}
,您的日志将显示 AnyClass
而不是包含日志语句的类。
答案 2 :(得分: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>();
}
}
答案 3 :(得分:2)
在.NET Core中,ILogger<T>
将自动为您注册。由于ILogger<T>
继承自ILogger
,因此您可以从ILogger<T>
请求IServiceProvider
的实例。
例如:
services.AddSingleton<ILogger>(svc => svc.GetRequiredService<ILogger<MyClassType>>());
请注意,只要您有一个非通用的ILogger<MyClassType>
构造函数参数,它就会返回一个ILogger
,因此,如果您需要多个参数,请考虑使用{ {1}}(或临时/或作用域)的ImplementationFactory覆盖。
答案 4 :(得分:2)
基于@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))
答案 5 :(得分:0)
我尝试使用server {
listen 80;
server_name test.myserver.com;
root /www/;
location = / { }
location /index.html { }
location / {
proxy_pass http://192.168.0.170;
}
}
(因为不再注入),注入ILogger
,然后在代码需要特定记录器时使用的方法(例如,它是一些自定义工厂您ILoggerFactory
在new
-在下面
但是对于您而言,您似乎想要LoggerFactory.CreateLogger("Logger Name")
ILogger<MyClass>
答案 6 :(得分:0)
此答案不一定适用于.net Core或发布者正在使用的任何依赖项注入。我在此搜索中寻找了一种在asp.net表单Web应用程序中使用Autofac修复此错误的方法。日志记录未“默认注册”的答案导致我将其添加到我的注册中:
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
现在它对我有用。这是我第二次搜索该答案并结束于此处,却忘记了如何第一次修复它。所以我想我会发布答案。
答案 7 :(得分:0)
这就是让 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>();
});