【问题标题】:Inheriting logging services from base class从基类继承日志服务
【发布时间】:2021-03-13 14:44:29
【问题描述】:

我有一个 .Net Core 3.1 API 控制器,其构造函数如下所示:

public class MachineListsController : ControllerBase
{
    private readonly jiWeb_ProdContext _context;
    private readonly ILogger _logger;
    private readonly ILoggingMessageService _loggingMessage;

    public MachineListsController(jiWeb_ProdContext context, ILogger<MachineListsController> logger, ILoggingMessageService loggingMessage)
    {
        _context = context;
        _logger = logger;
        _loggingMessage = loggingMessage;
    }

    public string Message { get; set; }

   ...
}

您可以看到我正在向其中注入一个 .Net Core 日志记录服务和数据库上下文。

然后我在我的控制器方法中使用这样的日志记录:

    [HttpGet("FactoryMachines/{factoryId}")]
    public async Task<ActionResult<IEnumerable<MachineList>>> GetMachinesForFactory(Guid factoryId)
    {
        var machineList = await _context.MachineList.Where(n => n.FactoryId == factoryId).ToListAsync();

        Message = _loggingMessage.GetLogSuccess(this.GetType().Name.ToString(), ControllerActions.GetAction, "FactoryMachines", factoryId.ToString());
        _logger.LogInformation(Message);
        return machineList;
    }

日志记录工作得很好,但我意识到我应该创建一个处理日志记录的基类,这样我就不必在我编写的每个控制器中添加或更改它。

于是我开始编写这个基本控制器:

[ApiController]
public class MyBaseController : ControllerBase
{
    readonly jiWeb_ProdContext _context;
    readonly ILogger _logger;
    readonly ILoggingMessageService _loggingMessage;

    public BaseController(jiWeb_ProdContext context, ILogger<BaseController> logger, ILoggingMessageService loggingMessage)
    {
        _context = context;
        _logger = logger;
        _loggingMessage = loggingMessage;
    }

}

然后我将控制器更改为从它继承如下:

public class MachineListsController : MyBaseController
{
    [HttpGet("FactoryMachines/{factoryId}")]
    public async Task<ActionResult<IEnumerable<MachineList>>> GetMachinesForFactory(Guid factoryId)
    {
        var machineList = await _context.MachineList.Where(n => n.FactoryId == factoryId).ToListAsync();

        return machineList;
    }
}

但我遇到了错误,我不确定下一步该做什么。

这是错误:

There is no argument given that corresponds to the required formal parameter 'context' of 'BaseController.BaseController(jiWeb_ProdContext, ILogger<BaseController>, ILoggingMessageService)'

具体来说,如何设置我的控制器,以便它们可以使用基类进行日志记录,这样我就不必为我创建的每个新控制器操作编写日志记录代码?

谢谢!

【问题讨论】:

  • 您的字段是 private 到基类。使它们受到保护,以便派生类可以访问它们
  • 这实际上可能是XY problem
  • @Nkosi 我尝试将它们设置为受保护,但仍然出现错误。我会谷歌 XY 谢谢你
  • 相同的错误或不同的错误。因为根据您目前所展示的内容,除了刚刚修复的内容之外,还会有其他错误。
  • @Nkosi 对不起,同样的错误。感谢您的帮助,我将学习 XY 问题并希望解决。

标签: entity-framework-core asp.net-core-webapi asp.net-core-3.1


【解决方案1】:

据我所知,如果基类构造方法包含值,我们应该在子类构造方法中传递它,并且您应该按照 Nkosi 注释将属性修改为受保护。

更多细节,您可以参考以下代码:

[ApiController]
public class MyBaseController : ControllerBase
{
    protected readonly ILogger _logger;

    public MyBaseController(ILogger<MyBaseController> logger)
    {
    
        _logger = logger;

    }

}

[Route("api/[controller]")]
public class MachineListsController : MyBaseController
{
    public MachineListsController(ILogger<MyBaseController> logger) :base(logger)
    {
    
    }


    [HttpGet]
    public IActionResult Get() {
         _logger.Log(Microsoft.Extensions.Logging.LogLevel.Trace,"aaa" );

        return Ok();
    }
}

我想知道,有没有办法在基类中进行日志记录?就像您在 MachineListsController 类中调用 _logger.Log 一样,可以将其移至基础吗?

据我所知,我们只能在 MachineListsController 的操作执行之前或 MachineListsController 的操作执行之后添加日志。

如果这符合您的要求,您可以尝试使用操作过滤器。

您可以将 iactionfilter 接口添加到基本控制器并覆盖 OnActionExecuted 和 OnActionExecuting 方法。

更多细节,您可以参考以下代码:

[Route("api/[controller]")]
[ApiController]
public class MyBaseController : ControllerBase, IActionFilter
{
    protected readonly ILogger _logger;

    public MyBaseController(ILogger<MyBaseController> logger)
    {
    
        _logger = logger;

    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        _logger.Log(Microsoft.Extensions.Logging.LogLevel.Trace, "aaa");
        int i = 0;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.Log(Microsoft.Extensions.Logging.LogLevel.Trace, "bbb");
        int i = 0;
    }
}

结果:

【讨论】:

  • 谢谢你的例子。我想知道,有没有办法在基类中进行日志记录?就像您在 MachineListsController 类中调用 _logger.Log 一样,可以将其移至基础吗?我问,因为那时基类会处理所有的日志记录。这样,当我编写新的控制器方法时,我可以从基本控制器继承,而不必在每个新控制器中编写日志代码。希望我能解释清楚,谢谢
  • 根据您的描述,我建议您可以尝试添加 iactionfilter 并覆盖基本控制器的 onactionexcuting 和 onactionexcuted 方法并在其中记录一些内容。详情可以参考我的更新回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 2011-02-21
  • 2018-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多