简体   繁体   English

使用Autofac解决MVC3中组件内部的控制器

[英]Resolving controllers inside component in MVC3 with Autofac

I have a component which is able to to check it controller's action is accessible for currently logged user. 我有一个组件可以检查当前登录用户是否可以访问控制器的操作。

public class ControllerAccessChecker : IControllerAccessChecker
{
    ILifetimeScope _scope;

    public ControllerAccessChecker(ILifetimeScope scope)
    {
        _scope = scope;
    }

    public bool IsAccessible<TController>(Expression<Action<TController>> action, RequestContext requestContext) where TController : Controller
    {
        var actionName = GetActionName(action);
        var result = false;

        using (var childScope = _scope.BeginLifetimeScope())
        {
            var controller = childScope.Resolve<TController>(); 
            result = HasActionPermission(requestContext, actionName, controller);
        }
        return result;
    }

    private static string GetActionName(LambdaExpression actionExpression)
    {
        object operand;
        if (actionExpression.Body as UnaryExpression != null)
        {
            operand = ((UnaryExpression)actionExpression.Body).Operand;
        }
        else
        {
            operand = actionExpression.Body;
        }
        MethodCallExpression methodCallExpression = (MethodCallExpression)operand;
        return methodCallExpression.Method.Name;
    }

    private static bool HasActionPermission(RequestContext requestContext, string actionName, ControllerBase controller)
    {
        var controllerContext = new ControllerContext(requestContext, controller);

        var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());

        var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

        return ActionIsAuthorized(controllerContext, actionDescriptor);
    }


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor == null)
            return false;

        AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);

        foreach (Filter authFilter in FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor).Where(x => x.Instance is IAuthorizationFilter))
        {
            ((IAuthorizationFilter)authFilter.Instance).OnAuthorization(authContext);

            if (authContext.Result != null)
                return false;
        }

        return true;
    }
}

As you can see I am injecting ILifetimeScope into constructor and I am not sure if this is good practice. 如您所见,我正在将ILifetimeScope注入到构造函数中,但不确定这是否是一种好习惯。 Also I am not sure if I am doing right thigs inside IsAccessible method. 另外,我不确定我是否在IsAccessible方法中执行正确的操作。 This Autofac's scope hierarchy approach is really confusing for me. Autofac的范围层次结构方法确实让我感到困惑。

I was thinking about some sort of abstract factory for controllers but it seems to be not easy to implement with Autofac. 我在考虑某种用于控制器的抽象工厂,但是用Autofac似乎并不容易实现。 I found some articles and answers here about using IIndex<,> and registration with .Keyed() but I don't think this is really what should be use in case like this. 我在这里找到了一些有关使用IIndex<,>以及向.Keyed()注册的文章和答案IIndex<,>但是我不认为这种情况下确实应该使用。 I mean I know what type I need so it should be easy just to ask for it. 我的意思是我知道我需要哪种类型,因此索要它应该很容易。

Rather than injecting the lifetime scope, you can use AutofacDependencyResolver.Current.RequestLifetimeScope - Unless you're using this outside a web context, I'd probably go with that. 您可以使用AutofacDependencyResolver.Current.RequestLifetimeScope而不是注入生命周期范围-除非您是在Web上下文之外使用AutofacDependencyResolver.Current.RequestLifetimeScope ,否则我可能AutofacDependencyResolver.Current.RequestLifetimeScope

One thing on the design of this: in IsAccessible you're resolving the actual controller, which also means you're resolving and instantiating all of its dependencies, all the way down the chain. 设计的一件事:在IsAccessible您正在解析实际的控制器,这也意味着您正在解析并实例化其所有依赖关系,一直到整个链。 If you're doing this in a menu system or somewhere that you're doing a lot of these on every request, that's a lot of controllers (and controller dependencies). 如果您是在菜单系统中执行此操作的,或者在每个请求中都执行许多操作的地方,则是很多控制器(和控制器相关性)。 And if your controller dependencies are, say, database connections or WCF service proxies... well, that could get pretty expensive just to check accessibility. 而且,如果您的控制器依赖项是数据库连接或WCF服务代理...那么,仅检查可访问性可能就变得非常昂贵。 Something to consider. 需要考虑的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM