使用SimpleInjector中的IAuthorizationFilter进行依赖注入

时间:2018-03-01 15:02:24

标签: c# asp.net-mvc simple-injector

我有一个PermissionFilter课,它从IAuthorizationFilter实施System.Web.Mvc。由于它具有已映射的依赖项,因此我想使用SimpleInjector来提供它。

我正在这样做(与Ninject合作):

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(DependencyResolver.Current.GetService(typeof(PermissionFilter)));
}

但我收到错误:

  

值不能为空。参数名称:实例

我试图从容器中获取PermissionFilter的实例:

var permissionFilter = container.GetInstance(typeof(PermissionFilter));
filters.Add(permissionFilter);

但是使用SimpleInjector,当它到达这个代码时:

container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

我收到InvalidOperationException消息:

  

首次调用GetInstance,GetAllInstances和Verify后,无法更改容器。请参阅https://simpleinjector.org/locked以了解容器锁定的原因。

1 个答案:

答案 0 :(得分:1)

在我写这个问题的时候,我被SO提示检查这个问题,并great answer通过Steven。在那里他说:

  

MVC全局过滤器只是一个实例列表。这意味着任何依赖项,例如过滤器,也会变成单例。这意味着您应该非常小心这种方法,因为在您的应用程序中偶然导致Captive Dependency非常容易。强制依赖性通常难以跟踪,通常只在测试或生产中弹出。

     

相反,您应该创建一个代理类,该代理类可以在使用过滤器时委托回容器/内核,因此它可以在现场解析实际过滤器。这可以防止强制性依赖。

所以,我最后编写了这个代理类:

public class AuthorizationFilterProxy<TFilter> : IAuthorizationFilter
    where TFilter : class, IAuthorizationFilter
{
    private readonly Container Container;

    public AuthorizationFilterProxy(Container container)
    {
        Container = container;
    }

    public void OnAuthorization(AuthorizationContext context)
    {
        Container.GetInstance<TFilter>().OnAuthorization(context);
    }
}

添加过滤器:

public static void RegisterGlobalFilters(
    GlobalFilterCollection filters, Container container)
{
    // Since PermissionFilter is a root type (i.e. directly resolved from the container),
    // it should be explicitly registered. This allows it to be verified.
    container.Register<PermissionFilter>();

    filters.Add(new AuthorizationFilterProxy<PermissionFilter>(container));
}