解决错误 - 无法解析“Serilog.ILogger”类型的服务

问题描述 投票:0回答:8

我正在尝试在ASP.NET核心应用程序(.NET框架)中实现SeriLog

以下是我迄今为止执行的步骤-

1) 在 Project.json 中添加了以下引用

"Serilog": "2.2.0",
"Serilog.Extensions.Logging": "1.2.0",
"Serilog.Sinks.RollingFile": "2.0.0",
"Serilog.Sinks.File": "3.0.0"

2) 在 Startup 类的构造函数中添加了以下几行 -

Log.Logger = new LoggerConfiguration()
           .MinimumLevel.Debug()
           .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "log-{Date}.txt"))
           .CreateLogger();

3)将以下行添加到 Startup 类的配置方法中 -

loggerFactory.AddSerilog();

4)像这样将记录器注入到 HomeController -

ILogger logger;

    public HomeController(ILogger logger)
    {
        this.logger = logger;
    }

5)在“关于”操作中,尝试记录这样的异常-

public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        try
        {
            throw new Exception("Serilog Testing");
        }
        catch (System.Exception ex)
        {
            this.logger.Error(ex.Message);
        }

        return View();
    }

运行我的应用程序时,出现以下错误 -

System.InvalidOperationException:无法解析类型的服务 尝试激活时出现“Serilog.ILogger” 'AspNetCore_SeriLog_Trial1.Controllers.HomeController'。在 Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp,类型 type,类型 requiredBy,布尔值 isDefaultParameterRequired)
在 lambda_method(Closure 、 IServiceProvider 、 Object[] ) 处 Microsoft.AspNetCore.Mvc.Internal.TypeActivatorCache.CreateInstance[TInstance](IServiceProvider serviceProvider,类型实现类型)位于 Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerActivator.Create(ControllerContext 控制器上下文)在 Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerFactory.CreateController(ControllerContext 上下文)在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__26.MoveNext()

有人可以帮我解决这个问题吗? Serilog 缺少任何配置吗?

asp.net-core asp.net-core-mvc serilog
8个回答
42
投票

尝试在控制器中执行以下操作。

    ILogger<HomeController> logger = null;
    public HomeController(ILogger<HomeController> _logger)
    {
        logger = _logger;
    }

41
投票

如果您需要使用

ILogger
(来自
Serilog
)而不是
ILogger<HomeController>
(来自
Microsoft.Extensions.Logging
),您可以在 Startup 类上注册
ILogger

services.AddSingleton(Log.Logger);

14
投票

您的控制器中有以下哪两行?

using Serilog;
using Microsoft.Extensions.Logging;

如果是前者 (

using Serilog;
) 那么这可能是你的问题。

当您注册服务时,您实质上是在说“当构造函数请求 Microsoft.Extensions.Logging.ILogger 时,向它们传递一个 Serilog 实例,因为我正在使用 Serilog 进行日志记录”,但随后在您的构造函数中 您不是要求 Microsoft.Extensions.Logging.ILogger,而是要求 Serilog.ILogger 并且您的应用程序变得混乱,因为您还没有定义要为

Serilog.ILoger
注入的服务,您已经为
Microsoft.Extensions.Logging.ILogger

定义一个

请记住,您正在实现 Microsoft 的 ILogger 接口:您的构造函数不需要知道您正在使用 Serilog...事实上,您并不希望它知道!重点是您可以随时将 Serilog 替换为不同的记录器,而无需更改代码。

在构造函数中将

using Serilog;
更改为
using Microsoft.Extensions.Logging;
,您将请求正确的服务类型


0
投票

您错过了在控制器构造函数中注入接口:

ILogger<HomeController> logger = null;

public HomeController(ILogger<HomeController> _logger)
{
    logger = _logger;
}

在 Program.cs 中,您还必须添加 UseSerilog:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseSerilog();

0
投票

My(!) 使用推荐的 Host.CreateApplicationBuilder(args); MS Learn:.Net 中的工作人员服务

NET7.0 的最简单解决方案

NuGetPackages:

  • 串行记录
  • Serilog.Extensions.Hosting
  • Serilog.Sinks.Console
  • Serilog.Sinks.File

    public static void Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                   .MinimumLevel.Debug()
                   .WriteTo.Console(LogEventLevel.Information)
                   .WriteTo.File(path:"logs/Dummylog-.txt",rollingInterval:RollingInterval.Day)
                   .CreateLogger();
    
    
                var builder = Host.CreateApplicationBuilder(args);
                var services = builder.Services;
                builder.Logging.ClearProviders();
    
                services.AddSerilog(Log.Logger)
                        .AddHostedService<Worker>();
                      
                IHost host = builder.Build();
                host.Run();
            }

在服务中我注入了 Serilog(!).ILogger MS 也有一个 ILogger 接口,我可以只写一个 using ,但是很懒


    private readonly Serilog.ILogger _logger;
    
            public Worker(Serilog.ILogger logger)
            {
                _logger = logger;
            }
    
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    _logger.Information("Worker running at: {time}", DateTimeOffset.Now);
                    await Task.Delay(1000, stoppingToken);
                }
            }
        }



-1
投票

我遇到了这个问题“在尝试激活‘Controller_Name’时无法解析类型‘interface_name’的服务....

通过在startup.cs中添加以下行,我已经解决了同样的问题:

services.AddScoped<interface_name, Controller_Name>();

-1
投票

我知道这是一个老问题,但我刚刚遇到这个问题并找到了不同的解决方案。

我将

Microsoft.Extensions.Logging
换成了
Serilog
,但我错过了将其从构造函数参数列表中删除的情况。

public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger logger)

一旦我删除该参数,错误就消失了。

public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)

看起来 OP 试图通过构造函数注入记录器,但应该为该控制器创建一个特定的记录器。您还可以将其设置为

static
,这样 每次运行此项目时仅创建 1 个记录器,而不是为该类的每个实例创建 1 个记录器。

public class HomeController : Controller
{
    private static readonly ILogger Logger = Log.ForContext<HomeController>();
    ...

    public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
    {
    ...
    }

    ...
}

显然,发生的情况是编译器默认尝试为构造函数提供一个

Microsoft.Extensions.Logging
记录器,而不是尝试匹配构造函数实际期望的
Serilog
记录器,所以这就是错误的来源。

© www.soinside.com 2019 - 2024. All rights reserved.