在 SimpleInjector 中使用 IAuthorizationFilter 进行依赖注入
Dependency injection with IAuthorizationFilter in SimpleInjector
我有一个 class PermissionFilter
实现了 System.Web.Mvc
的 IAuthorizationFilter
。由于它有已经映射的依赖项,我想使用 SimpleInjector 来提供它。
我正在做这个(与 Ninject 一起工作):
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(DependencyResolver.Current.GetService(typeof(PermissionFilter)));
}
但我收到错误:
Value cannot be null. Parameter name: instance
我试图从容器中获取 PermissionFilter
的实例:
var permissionFilter = container.GetInstance(typeof(PermissionFilter));
filters.Add(permissionFilter);
但是对于 SimpleInjector,当它到达这段代码时:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
我收到 InvalidOperationException
消息:
The container can't be changed after the first call to GetInstance, GetAllInstances and Verify. Please see https://simpleinjector.org/locked to understand why the container is locked.
在我写问题的时候,SO 提示我检查这个问题和 by Steven。他在那里说:
MVC global filters are just a list of instances. This means that any dependencies such filter has, also become singletons. This means you should be very careful with this approach, because it is really easy to accidentally cause a Captive Dependency in your application. Captive Dependencies are often hard to track and often only popup in testing or production.
Instead, you should create a proxy class that can delegate back to your container/kernel at the time the filter is used, so it can resolve the real filter on the spot. This prevents Captive Dependencies.
所以,我最终写了这个代理 class:
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));
}
我有一个 class PermissionFilter
实现了 System.Web.Mvc
的 IAuthorizationFilter
。由于它有已经映射的依赖项,我想使用 SimpleInjector 来提供它。
我正在做这个(与 Ninject 一起工作):
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(DependencyResolver.Current.GetService(typeof(PermissionFilter)));
}
但我收到错误:
Value cannot be null. Parameter name: instance
我试图从容器中获取 PermissionFilter
的实例:
var permissionFilter = container.GetInstance(typeof(PermissionFilter));
filters.Add(permissionFilter);
但是对于 SimpleInjector,当它到达这段代码时:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
我收到 InvalidOperationException
消息:
The container can't be changed after the first call to GetInstance, GetAllInstances and Verify. Please see https://simpleinjector.org/locked to understand why the container is locked.
在我写问题的时候,SO 提示我检查这个问题和
MVC global filters are just a list of instances. This means that any dependencies such filter has, also become singletons. This means you should be very careful with this approach, because it is really easy to accidentally cause a Captive Dependency in your application. Captive Dependencies are often hard to track and often only popup in testing or production.
Instead, you should create a proxy class that can delegate back to your container/kernel at the time the filter is used, so it can resolve the real filter on the spot. This prevents Captive Dependencies.
所以,我最终写了这个代理 class:
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));
}