c# - 如何在 .Net Core ActionFilterAttribute 中使用依赖注入(inject)?

标签 c# asp.net .net asp.net-core memorycache

AuthenticationRequiredAttribute 类

public class AuthenticationRequiredAttribute : ActionFilterAttribute
{
    ILoginTokenKeyApi _loginTokenKeyApi;
    IMemoryCache _memoryCache;

    public AuthenticationRequiredAttribute(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;

        _loginTokenKeyApi = new LoginTokenKeyController(new UnitOfWork());
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var memory = _memoryCache.Get(Constants.KEYNAME_FOR_AUTHENTICATED_PAGES);

        string requestedPath = filterContext.HttpContext.Request.Path;

        string tokenKey = filterContext.HttpContext.Session.GetString("TokenKey")?.ToString();

        bool? isLoggedIn = _loginTokenKeyApi.IsLoggedInByTokenKey(tokenKey).Data;

        if (isLoggedIn == null ||
            !((bool)isLoggedIn) ||
            !Constants.AUTHENTICATED_PAGES_FOR_NORMAL_USERS.Contains(requestedPath))
        {
            filterContext.Result = new JsonResult(new { HttpStatusCode.Unauthorized });
        }
    }
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
    }
}

家庭 Controller

public class HomeController : Controller
{
    IUserApi _userApi;
    ILoginTokenKeyApi _loginTokenKey;
    IMemoryCache _memoryCache;

    public HomeController(IUserApi userApi, ILoginTokenKeyApi loginTokenKey, IMemoryCache memoryCache)
    {
        _loginTokenKey = loginTokenKey;
        _userApi = userApi;

        _memoryCache = memoryCache;
    }

    [AuthenticationRequired] // There is AN ERROR !!
    public IActionResult Example()
    {
        return View();
    }
}

错误:

Error CS7036 There is no argument given that corresponds to the required formal parameter 'memoryCache' of 'AuthenticationRequiredAttribute.AuthenticationRequiredAttribute(IMemoryCache)' Project.Ground.WebUI

我的问题实际上是:我不能在属性类中使用依赖注入(inject)

我想在没有任何参数的情况下使用该属性。有解决办法吗?我使用依赖注入(inject),但它不能用于属性。我该如何使用它?

最佳答案

根据 the documentation ,您在这里有几个选择:

If your filters have dependencies that you need to access from DI, there are several supported approaches. You can apply your filter to a class or action method using one of the following:

ServiceFilter 或 TypeFilter 属性

如果您只是想让它快速运行,您可以只使用前两个选项之一将您的过滤器应用于 Controller 或 Controller 操作。执行此操作时,您的过滤器本身不需要是属性:

[TypeFilter(typeof(ExampleActionFilter))]
public IActionResult Example()
    => View();

ExampleActionFilter 然后可以只实现例如IAsyncActionFilter您可以使用构造函数注入(inject)直接依赖事物:

public class ExampleActionFilter : IAsyncActionFilter
{
    private readonly IMemoryCache _memoryCache;
    public ExampleActionFilter(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    { … }
}

您也可以使用 [ServiceFilter] 属性来获得相同的效果,但是您还需要在您的 启动

过滤器工厂

如果您需要更大的灵 active ,您可以实现自己的过滤器工厂。这允许您编写工厂代码来自己创建实际的过滤器实例。上述 ExampleActionFilter 的可能实现如下所示:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ExampleActionFilterAttribute : Attribute, IFilterFactory
{
    public bool IsReusable => false;

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return serviceProvider.GetService<ExampleActionFilter>();
    }
}

然后您可以使用 [ExampleActionFilter] 属性让 MVC 框架使用 DI 容器为您创建一个 ExampleActionFilter 的实例。

请注意,此实现与 ServiceFilterAttribute 所做的基本相同。只是自己实现它可以避免直接使用 ServiceFilterAttribute 并允许您拥有自己的属性。

使用服务定位器

最后,还有另一个快速选项可以让您完全避免构造函数注入(inject)。这使用服务定位器模式在过滤器实际运行时动态解析服务。因此,不是注入(inject)依赖项并直接使用它,而是从上下文中显式检索它:

public class ExampleActionFilter : ActionFilterAttribute
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var memoryCache = context.HttpContext.RequestServices.GetService<IMemoryCache>();

        // …
    }
}

关于c# - 如何在 .Net Core ActionFilterAttribute 中使用依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52724974/

相关文章:

asp.net - 如何使用 ASP.NET 网站每天发送 1000 多封电子邮件

.net - C# 线程和 SQL 连接

.net - 使用 RX Throttle 时的跨线程异常

c# - 从 C# 调用 Delphi DLL 产生意外结果

c# - 删除右键单击事件的 ListBoxItem 背景

asp.net - 如何使网站浏览器兼容不同的屏幕分辨率?

asp.net - 防止多线程网站消耗过多资源

c# - Try/Finally(没有 Catch)会冒泡异常吗?

c# - 将文件发送给 NAT 路由器后面的用户

c# - 在 C# 中处理 UAC 的正确方法