使用构造函数参数过滤的Ninject绑定属性

one*_*mer 16 attributes dependency-injection ninject filter asp.net-mvc-3

我尽可能多地阅读了这些答案,但它们似乎没有达到一个细节.

问题是当动作过滤器(由控制器注入的服务)绑定到相应的属性时,我一直无法弄清楚如何将参数/属性值从属性传递到其绑定过滤器.下面是代码,下面是我想要的假代码:

过滤器和属性

public class AuthorizationFilter : IAuthorizationFilter
{
    private readonly IAuthorizationService _authorizationService;
    private readonly UserRoles _requiredRoles;   // Enum

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles)
    {
        _authorizationService = authorizationService;
        _requiredRoles = requiredRoles;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Session == null)
            HandleUnauthorizedRequest(filterContext);
        else {
            var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles);
            if (!authorized)
                HandleUnauthorizedRequest(filterContext);
            // else TODO: deal with cache... 
        }
    }
}

public class RequireRolesAttribute : FilterAttribute
{
    public readonly UserRoles RequiredRoles;

    public RequireRolesAttribute(UserRoles requiredRoles)
    {
        RequiredRoles = requiredRoles;
    }        
}
Run Code Online (Sandbox Code Playgroud)

过滤器/属性绑定

kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0)
      .WhenControllerHas<RequireRolesAttribute>();
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>();
Run Code Online (Sandbox Code Playgroud)

这应该确保用[RolesRequired]修饰的任何控制器/动作都绑定到过滤器.到现在为止还挺好.现在我想通过属性声明角色(很像股票AuthorizeAttribute)并将这些值传递给实际执行授权的过滤器.

预期/假冒代码:

[RequireRoles(UserRoles.Author)]
public ActionResult Index()
{
    // blah
}
Run Code Online (Sandbox Code Playgroud)

特别,

如何通知AuthorizationFilter角色?filter/ninject可以访问传递给属性构造函数的参数吗?过滤器/ ninject可以从属性公共属性中提取它们吗?

作为参考,这些文章是一个巨大的帮助,但不回答这一点:

asp.net mvc的Ninject和Filter属性的依赖注入

自定义授权MVC 3和Ninject IoC

BZ,Remo Gloor,其他......我怎么能做到这一点?

one*_*mer 20

我已经弄明白了(感谢Remo的指示和文档).

使用适当的.WithConstructorArgument扩展,无论您是绑定到Controller还是Action过滤器.例如,绑定我的动作过滤器如下所示:

kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>()
      .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles", o => o.RequiredRoles);
Run Code Online (Sandbox Code Playgroud)

一旦我理解了Func <>签名,一切都变得清晰了.我发现处理这个的最好方法是

  1. 使我的属性的扩展类型特定

    .WithConstructorArgumentFromActionAttribute<TAttribute>()
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过lambda从回调对象(您的属性)获取值:

    ("argumentName", o => o.PropertyName)
    
    Run Code Online (Sandbox Code Playgroud)


kda*_*tha 9

并将BindFilter扩展方法纳入范围不要忘记添加;

using Ninject.Web.Mvc.FilterBindingSyntax;
Run Code Online (Sandbox Code Playgroud)

  • 这不是答案,应该作为对解决方案答案的评论发布. (16认同)