我有一个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以了解容器锁定的原因。
答案 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));
}