使用 Autofac 解析 MVC3 中组件内的控制器
本文关键字:控制器 组件 Autofac 解析 MVC3 使用 | 更新日期: 2023-09-27 17:56:00
我有一个组件,能够检查当前登录的用户是否可以访问控制器的操作。
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;
}
}
如您所见,我正在将ILifetimeScope
注入构造函数,我不确定这是否是好的做法。我也不确定我是否在方法中做正确的事情IsAccessible
。这种Autofac的范围层次结构方法对我来说真的很困惑。
我正在考虑某种控制器的抽象工厂,但使用 Autofac 实现似乎并不容易。我在这里找到了一些关于使用 IIndex<,>
和注册.Keyed()
的文章和答案,但我认为在这种情况下,这真的不应该使用。我的意思是我知道我需要什么类型,所以要求它应该很容易。
与其注入生命周期范围,不如使用 AutofacDependencyResolver.Current.RequestLifetimeScope
- 除非您在 Web 上下文之外使用它,否则我可能会使用它。
关于这个设计的一件事:IsAccessible
你正在解析实际的控制器,这也意味着你要解析和实例化它的所有依赖项,一直到链上。如果你在菜单系统中执行此操作,或者在某个地方对每个请求都做很多这些操作,那就是很多控制器(和控制器依赖项)。如果您的控制器依赖项是数据库连接或 WCF 服务代理...好吧,仅仅为了检查可访问性,这可能会变得非常昂贵。需要考虑的事情。