Autofac - 带有 OWIN 的 SignalR.获取对 ContainerBuilder 的引用

Autofac - SignalR with OWIN. getting reference to the ContainerBuilder

我有一个使用 Autofac 的现有 MVC 4 应用程序,我还有其他包含 autofac 模块的程序集。如果没有 SignalR/autofac 集成,就 IOC 而言,我的应用程序可以完美运行。我添加了 SignalR 集线器,我试图通过构造函数将依赖项注入其中。我已经按照文档并实现了代码示例。

http://autofac.readthedocs.org/en/latest/integration/signalr.html

结果如下 class:

public class SignalRConfig
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();
        var config = new HubConfiguration();

        Assembly thisAssembly = typeof(SignalRConfig).Assembly;

        builder.RegisterHubs(thisAssembly);

        var container = builder.Build();
        config.Resolver = new AutofacDependencyResolver(container);


        app.UseAutofacMiddleware(container);
        app.MapSignalR("/signalr", config);
    }
}

这与添加到我的 AssemblyInfo.cs

的这一行有关
[assembly: OwinStartup(typeof(SignalRConfig))]

但它在运行时不工作,因为我的集线器没有无参数构造函数,它无法解析依赖关系。我的假设是我正在创建一个新的 ContainerBuilder(根据文档)并且该实例没有注册任何内容。我实际上想要对在我的模块周围传递的 ContainerBuilder 的引用,它知道我所有已注册的类型。我只是不知道该怎么做。现有的IOC代码从application_start运行到global.asax,SignalRConfig同时运行。我不想将 ContainerBuilder 保持在一个单例中,因为它感觉很脏,但我找不到任何其他解决方案。

这是我的 nuget 包配置的一部分,显示了版本号等

  <package id="Autofac" version="3.5.2" targetFramework="net451" />
  <package id="Autofac.Mvc4" version="3.1.0" targetFramework="net40" />
  <package id="Autofac.Owin" version="3.1.0" targetFramework="net451" />
  <package id="Autofac.SignalR" version="3.0.1" targetFramework="net451" />
  <package id="Autofac.WebApi" version="3.1.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.SignalR" version="2.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.SignalR.JS" version="2.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi" version="4.0.20710.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.Owin" version="3.0.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Security" version="3.0.0" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />

听起来您正在将旧版 IIS 托管机制 (Application_Start) 与新的 OWIN 托管 (OwinStartup) 混合使用,这将很难纠正。

如果您使用 OWIN 托管您的应用程序,我建议将整个启动切换到 OWIN(至少是启动逻辑),这样您就不必尝试同步对容器的访问或传递东西.如果愿意,您仍然可以在 Global.asax 中保留其他事件处理程序(Application_Error 等),只需在 OWIN 启动 class.

中统一启动逻辑即可

您仍然可以通过将 "layers" 分成不同的启动 class 被调用的 es 来保持事情的整洁。

public static class Startup
{
  public static void Configuration(IAppBuilder app)
  {
    var container = DependencyConfiguration.Configure(app);
    SignalRConfiguration.Configure(app, container);
    MvcConfiguration.Configure(app, container);
  }
}

public static class DependencyConfiguration
{
  public static IContainer Configure(IAppBuilder app)
  {
    var builder = new ContainerBuilder();
    builder.RegisterHubs(typeof(SignalRConfiguration).Assembly);
    var container = builder.Build();
    app.UseAutofacMiddleware(container);
    return container;
  }
}

public static class SignalRConfiguration
{
  public static void Configure(IAppBuilder app, IContainer container)
  {
    var config = new HubConfiguration();
    config.Resolver = new AutofacDependencyResolver(container);
    app.MapSignalR("/signalr", config);
  }
}

...等等。重要的一点是您已经立即注册了所有依赖项,并且首先添加了 Autofac 中间件。然后,您可以传递容器以用于各个应用程序类型设置(就像您在 SignalR 中看到的那样)。

然后 bootstrap 整个事情与主启动 class:

[assembly: OwinStartup(typeof(Startup))]

这有很多好处。您回避了 运行 进入的竞争条件;您不需要尝试同步或重新排序;你有很多控制权。如果您想移植,它还会为 ASP.NET vNext 设置一个更好的位置,因为那时一切都是 OWIN。