首页 > 解决方案 > 如何使用具有 ActionFilters 的通用基本控制器

问题描述

我正在使用ILogger<T>并希望它包含在我的基本控制器中,因为每个控制器都应该使用它。

我将每个派生类定义为UsersController : BaseController<UsersController>

在我的基类中,我分配ILogger<T>了哪个工作正常,直到我尝试访问我的 ActionFilter 中的控制器,我需要知道如何转换它。

我如何实现这一目标或以更好的方式完成同样的事情。

// Base Controller
public class BaseController<T> : ControllerBase
{
    protected readonly IOptions<AppSettings> _appSettings;
    protected readonly ILogger<T> _logger;
}

// Instance Controller
public class UsersController : BaseController<UsersController>
{
    public UsersController(ILogger<UsersController> logger,
        IOptions<AppSettings> appSettings) 
        : base(logger, appSettings)
    {
        ...
    }

// ActionFilter used to set viewbag on all pages/layout pages
public class ViewBagActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        // Can't use typeof() or nameof()
        if (context.Controller.GetType().BaseType.Name == "BaseController")
        {
            // This doesn't work either
            var controller = context.Controller as BaseController;
            controller.ViewBag.Username = controller?.User?.Username;
        }

        base.OnResultExecuting(context);
    }
}

标签: c#asp.net-core

解决方案


我不知道这是否会有所帮助,但ILogger<T>继承自ILogger所以你可以让你的基本控制器不是通用的:

public class BaseController : ControllerBase
{
    protected readonly IOptions<AppSettings> _appSettings;
    protected readonly ILogger _logger;
}

并且您继承的控制器中的构造函数仍然可以工作。


推荐阅读