prosource

에서 종속성 주입을 사용하려면 어떻게 해야 합니까?NetCore 작업 필터 특성?

probook 2023. 6. 22. 21:57
반응형

에서 종속성 주입을 사용하려면 어떻게 해야 합니까?NetCore 작업 필터 특성?

인증 필수 특성 클래스

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

홈 컨트롤러

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'의 필수 형식 매개 변수 'memoryCache'에 해당하는 인수가 지정되지 않았습니다.인증 필수 특성('IMMemoryCache)' 프로젝트입니다.접지.웹UI

사실문제는: 저는 속성 클래스에서 의존성 주입을 사용할 수 없습니다.

매개 변수 없이 해당 속성을 사용하고 싶습니다.그것을 해결할 방법이 있습니까?종속성 주입을 사용하지만 속성에 사용할 수 없습니다.어떻게 사용합니까?

설명서에 따르면 다음과 같은 몇 가지 옵션이 옵션은 다음과 같습니다.

필터에 DI에서 액세스해야 하는 종속성이 있는 경우 지원되는 몇 가지 방법이 있습니다.다음 중 하나를 사용하여 클래스 또는 작업 방법에 필터를 적용할 수 있습니다.

ServiceFilter 또는 TypeFilter 특성

이 작업을 빨리 수행하려면 처음 두 가지 옵션 중 하나를 사용하여 컨트롤러 또는 컨트롤러 작업에 필터를 적용하면 됩니다.이 작업을 수행할 때 필터가 속성일 필요는 없습니다.

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

ExampleActionFilter그러면 다음과 같이 구현할 수 있으며 생성자 주입을 사용하여 직접적으로 의존할 수 있습니다.

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

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

사용할 수도 있습니다.[ServiceFilter]동일한 효과를 얻기 위해 대신 속성을 사용하지만, 또한 등록해야 합니다.ExampleActionFilter의존성 주입 용기를 사용하여Startup.

필터 팩토리

더 많은 유연성이 필요한 경우 자체 필터 팩토리를 구현할 수 있습니다.이렇게 하면 공장 코드를 작성하여 실제 필터 인스턴스를 직접 생성할 수 있습니다.위에 대한 가능한 구현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 프레임워크가 인스턴스를 생성하도록 하는 속성ExampleActionFilterDI 컨테이너를 사용합니다.

이 구현은 기본적으로 다음과 같습니다.ServiceFilterAttribute그렇습니다. 단지 직접 구현하면 사용할 필요가 없습니다.ServiceFilterAttribute직접 사용할 수 있으며 고유한 속성을 가질 수 있습니다.

서비스 로케이터 사용

마지막으로 생성자 주입을 완전히 피할 수 있는 다른 빠른 옵션이 있습니다.필터가 실제로 실행될 때 서비스 로케이터 패턴을 사용하여 서비스를 동적으로 확인합니다.따라서 종속성을 주입하고 직접 사용하는 대신 컨텍스트에서 명시적으로 검색합니다.

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

        // …
    }
}

건설현서해대신는하결에장,대신▁instead,ActionExecutingContext.HttpContext.RequestServices요청 시 요청의 서비스 컨테이너에 대한 참조를 제공해야 합니다.

그래서:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var svc = filterContext.HttpContext.RequestServices;
    var memCache = svc.GetService<IMemoryCache>();
    //..etc

.Net Core 5의 경우 아래 구문이 저에게 효과가 있었습니다.

 IAppUserService _appUserService = (IAppUserService)context.HttpContext.RequestServices.GetService(typeof(IAppUserService));

언급URL : https://stackoverflow.com/questions/52724974/how-can-i-use-dependency-injection-in-a-net-core-actionfilterattribute

반응형