使用Ninject进行过滤器构造依赖注入

11

我正在尝试找到一种使用Ninject将构造函数依赖项注入到过滤器中的方法。我发现许多文章描述了属性注入,但这种方式现在已经被建议停用,其余的文章涉及复杂的设置,如工厂、定位器、全局包装器或存根属性。

由于MVC允许您几乎覆盖其操作的任何部分,我认为创建自己的过滤器提供程序应该很简单,类似于创建自己的依赖项解析器。

现在正确的允许注入的方法是什么,或者使用某些类型的过滤器是否会更容易?

 public class UserValidationAttribute : ActionFilterAttribute
 {
    private IRepository repository;

    public UserValidationAttribute(IRepository repository)
    {
        this.repository = repository;
    }
}

1
请注意 - 一般来说,属性注入应用于可选依赖项,但要使用构造函数注入必需依赖项(这有点合理 - 没有必需的依赖项,您无法构造类型,但是基于容器中可用的服务,可能不会注入属性) - Charleh
我现在已经实现了一个方法,其中你有一个全局过滤器,它通过检查是否存在令牌属性来确定是否适用。我目前不理解的是,当我在操作上使用令牌属性并使用 filterContext.ActionDescriptor.IsDefined(typeof(MyTokenAttribute), true) 时,我得到 true,但如果我只将令牌属性放在控制器上,则为 false - John Freebs
3个回答

18

有一种使用构造函数注入的方法。

首先,您将属性替换为一个“空”的属性,这只是一个标记。

public class UserValidationAttribute : Attribute { }

然后你需要创建一个过滤器类作为 IActionFilter

public class UserValidationFilter : IActionFilter
{
    private readonly IRepository repository;

    public UserValidationFilter(IRepository repository)
    {
        this.repository = repository;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //do something
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //do something
    }      
}

然后你可以像下面这样将其注册:

private static void RegisterServices(IKernel kernel)
{
    kernel.BindFilter<UserValidationFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<UserValidationAttribute>();
}

如果您的属性本身具有构造函数参数,则可以像这样传递它们:
kernel.BindFilter<UserValidationFilter>(FilterScope.Action, 0)
    .WhenActionMethodHas<UserValidationAttribute>();
    .WithConstructorArgumentFromActionAttribute<UserValidationAttribute>("myParameter", attr => attr.MyParameter);

BindFilter 语法是 Ninject.Web.Mvc.FilterBindingSyntax 的一部分。


2

假设属性是元数据的一部分,这意味着它应该在编译时实例化,那么任何 ioc 容器都无法向属性注入存储库。容器在运行时操作。


0
如果您想向文件注入依赖项,建议使用属性注入而不是构造函数注入。
public class UserValidationAttribute : ActionFilterAttribute
{
    [Inject]
    private IRepository repository { get; set; }

    public UserValidationAttribute()
    {
    }
}

https://dev59.com/KWw05IYBdhLWcg3wgyLI#7192754


这个依赖是一个似乎是必需的仓库,所以应该通过构造函数注入。此外,我觉得在类中随意使用IoC的魔法属性是一种不好的模式。大多数IoC容器今天都支持将其注入到MVC过滤器中,包括Ninject、Unity v3和StructureMap。 - Thiago Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接