C# Autofac-带OWIN的信号机。获取对ContainerBuilder的引用

C# Autofac-带OWIN的信号机。获取对ContainerBuilder的引用,c#,asp.net-mvc-4,signalr,autofac,C#,Asp.net Mvc 4,Signalr,Autofac,我有一个使用Autofac的现有MVC4应用程序,我还有其他程序集,其中包含Autofac模块。没有信号器/autofac集成,就IOC而言,我的应用程序工作得非常完美。我已经添加了信号集线器,我正试图通过构造函数将依赖项注入其中。我遵循了文档并从中实现了代码示例 这将导致以下类别: public class SignalRConfig { public void Configuration(IAppBuilder app) { var builder = ne

我有一个使用Autofac的现有MVC4应用程序,我还有其他程序集,其中包含Autofac模块。没有信号器/autofac集成,就IOC而言,我的应用程序工作得非常完美。我已经添加了信号集线器,我正试图通过构造函数将依赖项注入其中。我遵循了文档并从中实现了代码示例

这将导致以下类别:

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);
    }
}
这与添加到my AssemblyInfo.cs的这一行连接

[assembly: OwinStartup(typeof(SignalRConfig))]
但它在运行时不起作用,因为我的集线器没有无参数构造函数,并且它无法解析依赖关系。我的假设是,我正在创建一个新的ContainerBuilder(根据文档),并且这个实例上没有注册任何内容。实际上,我想要的是对ContainerBuilder的引用,它在我的模块中传递,这些模块知道我所有注册的类型。我只是不知道怎么做。现有IOC代码从global.asax上的应用程序_start运行,同时运行SignalConfig。我不想把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托管机制(
应用程序启动
)与新的OWIN托管机制(
OwinStartup
)混合在一起,这将很难纠正

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

您仍然可以通过将“层”划分为不同的启动类来保持事物的整洁

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中间件。然后,您可以将容器传递给各个应用程序类型设置中使用的容器(就像您在signar中看到的那样)

然后用主启动类引导整个过程:

[assembly: OwinStartup(typeof(Startup))]

这有很多好处。你避开了你所遇到的比赛条件;你不需要尝试同步或重新排序;你有很多控制权。如果您想移植ASP.NET vNext,它还为您提供了一个更好的位置,因为一切都已就绪。

谢谢您的详细回答。我将按照您的建议重新调整我的启动代码。