public void OnAuthorization(AuthorizationFilterContext context)
        {
            IServiceProvider             services      = context.HttpContext.RequestServices;
            object                       authorization = services.GetRequiredService(serviceType);
            IAuthorizationResultAccessor accessor      = services.GetRequiredService <IAuthorizationResultAccessor>();
            PolicyResult                 policyResult  = (PolicyResult)tryAuthorizeMethod.Invoke(authorization, new object[] { policyExpression });
            SortedSet <string>           succeeded     = new SortedSet <string>();
            SortedSet <string>           failed        = new SortedSet <string>();
            SortedSet <string>           notHandled    = new SortedSet <string>();

            switch (policyResult)
            {
            case PolicyResult.Success:
                succeeded.Add(policyExpression);
                break;

            case PolicyResult.Failed:
                failed.Add(policyExpression);
                break;

            case PolicyResult.NotHandled:
            default:
                notHandled.Add(policyExpression);
                break;
            }

            PolicyOnlyExpression exp    = new PolicyOnlyExpression(policyExpression, policyResult);
            PolicyExpressionRoot root   = new PolicyExpressionRoot(exp);
            AuthorizationResult  result = new AuthorizationResult(root);

            if (accessor.Result == null)
            {
                accessor.Result = result;
            }
            else
            {
                result.CombineAsAnd(accessor.Result);
                accessor.Result = result;
            }

            bool overall = false;

            switch (result.Result)
            {
            case PolicyResult.Success:
                overall = true;
                break;

            case PolicyResult.Failed:
                break;

            case PolicyResult.NotHandled:
            default:
                if (!failedIfNotHandled)
                {
                    overall = true;
                }
                break;
            }
            if (overall)
            {
                return;
            }
            switch (failedAction)
            {
            case AuthorizationFailedAction.KeepUnauthorized:
                return;

            case AuthorizationFailedAction.Return401:
                context.Result = new HttpUnauthorizedResult();
                return;

            case AuthorizationFailedAction.CustomHandler:
                break;
            }

            // custom handler
            IAuthorizationDeclarationCache cache = services.GetRequiredService <IAuthorizationDeclarationCache>();
            AuthorizationDeclarationInfo   info  = null;

            switch (context.ActionDescriptor)
            {
            case ControllerActionDescriptor controllerActionDescriptor:
                info = cache.Get(controllerActionDescriptor);
                break;

            case CompiledPageActionDescriptor compiledPageActionDescriptor:
                info = cache.Get(compiledPageActionDescriptor);
                break;

            default:
                throw new Exception($"not handled with action descriptor of type {context.ActionDescriptor.GetType().Name}");
            }

            if (info != null &&
                info.Declaration != AuthorizationDeclaration.No &&
                info.FailedAction == AuthorizationFailedAction.CustomHandler &&
                info.FailedHandler != null)
            {
                IActionResult actionResult = info.FailedHandler.Execute(context.HttpContext, result);
                if (actionResult != null)
                {
                    context.Result = actionResult;
                    return;
                }
                else
                {
                    // not handled
                    throw new Exception($"not handled");
                }
            }
            throw new Exception($"no handler set for type {context.ActionDescriptor.GetType().Name}");
        }