C# 无法从Microsoft.Extensions.Logging解析ILogger
我已经这样配置了控制台应用程序的C# 无法从Microsoft.Extensions.Logging解析ILogger,c#,.net,dependency-injection,.net-core,ilogger,C#,.net,Dependency Injection,.net Core,Ilogger,我已经这样配置了控制台应用程序的Main var services = new ServiceCollection() .AddLogging(logging => logging.AddConsole()) .BuildServiceProvider(); 然后我尝试在另一个类中使用它 private readonly ILogger _logger; public MyClass(ILogger log
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'
我试过解决办法,但对我不起作用
编辑
根据雅科夫下面的评论,我能够通过这样做正确地解决它
public MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
公共MyClass(ILogger记录器)
{
_记录器=记录器;
}
我希望在最初的
BuildServiceProvider
中有此功能,但每次我想使用记录器(或创建自己的ILogger)时,我都必须重复此功能。我假设您使用的是.net core 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 void配置服务(IServiceCollection服务)
{
配置(选项=>
{
//此lambda确定给定请求是否需要非必要cookie的用户同意。
options.checkApprovered=context=>true;
options.MinimumSameSitePolicy=SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//服务在这里注册吗?还有你想要的其他东西吗
services.AddLogging(配置=>
{
config.AddDebug();
config.AddConsole();
//等
});
}
编辑:我已经为你写了一个简单的程序来展示它是如何工作的
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>();
}
}
公共类MyClass
{
专用只读ILogger\u记录器;
公共MyClass(ILogger记录器)
{
_记录器=记录器;
}
public void MyFunc()
{
_logger.Log(LogLevel.Error,“我的消息”);
}
}
公共课程
{
公共静态void Main(字符串[]args)
{
var services=newservicecolection().AddLogging(logging=>logging.AddConsole());
services.AddSingleton();//Singleton还是transient?!
var s=services.BuildServiceProvider();
var myclass=s.GetService();
}
}
编辑:程序的输出:
ILogger
在默认情况下不再注册,但已注册。如果仍要使用ILogger,可以通过以下方式(Startup.cs)手动注册它:
因此:
public void配置服务(IServiceCollection服务)
{
var serviceProvider=services.BuildServiceProvider();
var logger=serviceProvider.GetService();
服务。AddSingleton(类型(ILogger),记录器);
...
}
ILogger现在将通过.NET Core中的构造函数注入进行解析,
ILogger
将自动为您注册。由于ILogger
继承自ILogger
,您可以从iSeries Provider
请求ILogger
的实例
例如:
services.AddSingleton(svc=>svc.GetRequiredService())代码>
请注意,只要有非泛型的ILogger
构造函数参数,这将返回一个ILogger
,因此如果需要多个构造函数参数,请使用AddSingleton
(或瞬态/或作用域)专门为该实例创建它实现工厂覆盖。我在尝试使用ILogger
(因为它不再被注入)时使用的方法,例如注入ILogger工厂
,然后当你的代码需要一个特定的记录器时(比如你正在创建的某个自定义工厂,LoggerFactory.CreateLogger(“记录器名称”)
-如下
但对于您的情况,看起来您需要一个ILogger
此答案不一定适用于.net Core或海报正在使用的任何依赖项注入。我在asp.net forms web应用程序中使用Autofac查找修复此错误的方法时遇到了此问题。日志记录未“默认注册”的答案导致我将此添加到我的注册中:
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
builder.RegisterType().As().SingleInstance();
RegisterGeneric(typeof(Logger)).As(typeof(ILogger)).SingleInstance();
现在它对我有效了。这是我第二次搜索这个答案,结果到了这里,我忘记了第一次是如何修复的。所以我想我应该发布我的答案。正如一篇评论中所指出的,接受的答案有一个问题,BuildServiceProvider
不应该在ConfigureServices
中使用,因为它创建了每个单例的副本(事实上,是整个DI容器的副本)。这里有一个避免该问题的替代行。在ConfigureServices
中,添加该行
services.AddSingleton<Microsoft.Extensions.Logging.ILogger>(provider =>
provider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<AnyClass>>());
services.AddSingleton(提供者=>
provider.GetRequiredService());
其中,AnyClass
可以是任何类,如接受答案中所述。这会将ILogger
的分辨率重定向到ILogger
的分辨率
与公认的答案一样,这个选项的缺点是Serilog的SourceContext
将设置为AnyClass
。因此,如果Serilog配置包含{SourceContext}的outputTemplate
,您的日志将显示AnyClass
,而不是包含日志语句的类。基于@answer了解如何注册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))
var services=newservicecolection()
.AddLogging(logging=>logging.AddConsole())
.BuildServiceProvider();
services.AddSingleton()
services.Add(servicescriptor.description(typeof(ILogger)、typeof(Logger)、ServiceLifetime.Scoped))
<代码>,PAR在哪里?
public class MyClass
{
private readonly ILoggerFactory _loggerFactory;
public MyClass(ILoggerFactory loggerFactory)
{
_loggerFactory = _loggerFactory;
}
public void MyFunc()
{
new MyNewThatsASpecialCase(_loggerFactory.CreateLogger("MyNewThatsASpecialCase"));
}
}
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().SingleInstance();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
services.AddSingleton<Microsoft.Extensions.Logging.ILogger>(provider =>
provider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<AnyClass>>());
var services = new ServiceCollection()
.AddLogging(logging => logging.AddConsole())
.BuildServiceProvider();
services.AddSingleton<ILoggerFactory, LoggerFactory>()
services.Add(ServiceDescriptor.Describe(typeof(ILogger<>),typeof(Logger<>),ServiceLifetime.Scoped))