6

我有一个旧版 Web.Forms 应用程序已部分重写为 MVC。MVC 部分使用 autofac 作为依赖注入容器。

MVC 部分定义了自定义过滤器:

public class CustomActionFilter : ActionFilterAttribute
{
    protected ILogger Logger { get; set; }
    public CustomActionFilter(ILogger logger) { Logger = logger; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Logger.Log("OnActionExecuting");
    }
}

在 web.config 中禁用 Web.Forms 集成时,它可以正常工作。然而,当我尝试使用 Web.Forms autofac 集成时,我得到了与AutofacFilterProviderautofac 内部(堆栈跟踪)中某处相关的 NullReferenceException。

请注意,它CustomActionFilter已注册为全局过滤器,因此它是使用 autofac 注册的:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(DependencyResolver.Current.GetService<CustomActionFilter>());
    }
}

我试过了:

  1. 为 MVC 和 Web.Forms 使用单独的容器 - 结果相同
  2. 使用属性注入而不是构造函数 - 结果相同
  3. 在 web.forms 页面上显式触发依赖项解析(像这样) - 有效

所以,问题是,有没有办法为 MVC 和 web.forms 部分提供幕后依赖解析。我是 autofac 的新手,对依赖注入容器也有些陌生,所以我可能会错过一些明显的东西。

更新:错误与自定义过滤器无关。如果我删除对自定义过滤器的所有引用,则错误行为仍然相同,甚至堆栈跟踪也是如此。

4

1 回答 1

6

实际上有两个错误?在导致此行为的 Autofac 中:

错误 #1:作为问题 351修复的副作用,AutofacDependencyResolver需要在创建的 Request bound 中注册LifeTimeScope。MVC 集成可以做到这一点,但 Winforms 集成当然不会。

漏洞?#2: theRequestLifetimeScopeProviderContainerProviderstoresILifetimeScope使用相同的键创建HttpContext.Current.Items

static ILifetimeScope LifetimeScope
{
    get { return (ILifetimeScope)HttpContext.Current.Items[typeof(ILifetimeScope)]; }
    set { HttpContext.Current.Items[typeof(ILifetimeScope)] = value; }
}

所以这里有一点竞争条件,因为取决于哪个模块首先执行,WebForms 或 MVC intergartion ILifetimeScope 获胜。因此,如果 WebForms 模块获胜,AutofacDependencyResolver则不会被注册,并且您会得到很好的非描述性异常。

修复/解决方法:

但是有一个简单的解决方法:您只需要在其中注册AutofacDependencyResolverContainerProvider requestLifetimeConfiguration因此无论哪个获胜(WebForm 与 MVC)AutofacDependencyResolver都将始终注册:

var autofacDependencyResolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(autofacDependencyResolver);
_containerProvider = new ContainerProvider(container, requestContainerBuilder => 
     requestContainerBuilder.RegisterInstance(autofacDependencyResolver)
     .As<AutofacDependencyResolver>());
于 2013-08-21T09:41:50.280 回答