如何在.Net Core ActionFilterAttribute中使用依赖注入? [英] How can I use Dependency Injection in a .Net Core ActionFilterAttribute?

查看:959
本文介绍了如何在.Net Core ActionFilterAttribute中使用依赖注入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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)
    {
    }
}

HomeController

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();
    }
}

错误:


错误CS7036没有给出与
'AuthenticationRequiredAttribute.AuthenticationRequiredAttribute(IMemoryCache)'Project.Ground的
必需形式参数'memoryCache'相对应的参数。 .WebUI

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

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

我想使用没有任何参数的属性。有解决方案吗?我使用依赖注入,但不能用于属性。我如何使用它?

I want to use that attribute without any parameter. Is there any solution to solve it? I use dependency injection but it cant be used for attributes. How to i can use it?

推荐答案

根据文档,您可以在此处选择以下几种方法:

As per the documentation, you have a few options here:


如果过滤器具有需要从DI访问的依赖项,则有几种受支持的方法。您可以使用以下一种方法将过滤器应用于类或操作方法:

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:

  • ServiceFilterAttribute
  • TypeFilterAttribute
  • IFilterFactory implemented on your attribute



ServiceFilter或TypeFilter属性



如果您只是想快速进行此操作,则可以使用前两个选项之一将过滤器应用于控制器或控制器动作。这样做时,您的过滤器本身不必是属性:

ServiceFilter or TypeFilter attributes

If you just want to get this working quickly, you can just use one of the first two options to apply your filter to a controller or a controller action. When doing this, your filter does not need to be an attribute itself:

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

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

The ExampleActionFilter can then just implement e.g. IAsyncActionFilter and you can directly depend on things using constructor injection:

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

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

您也可以使用 [ServiceFilter] 属性来获得相同的效果,但是您还需要在您的启动中,使用依赖项注入容器注册您的 ExampleActionFilter

You can also use the [ServiceFilter] attribute instead to get the same effect but then you will also need to register your ExampleActionFilter with the dependency injection container in your Startup.

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

If you need more flexibility, you can implement your own filter factory. This allows you to write the factory code to create the actual filter instance yourself. A possible implementation for the above ExampleActionFilter could look like this:

[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 的实例。

You can then use that [ExampleActionFilter] attribute to make the MVC framework create an instance of the ExampleActionFilter for you, using the DI container.

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

Note that this implementation is basically the same thing that ServiceFilterAttribute does. It’s just that implementing it yourself avoids having to use the ServiceFilterAttribute directly and allows you to have your own attribute.

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

Finally, there is another quick option that allows you to avoid constructor injection completely. This uses the service locator pattern to resolve services dynamically when your filter actually runs. So instead of injecting the dependency and using it directly, you retrieve it explicitly from the context:

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

        // …
    }
}

这篇关于如何在.Net Core ActionFilterAttribute中使用依赖注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆