【问题标题】:Autofac - SignalR with OWIN. getting reference to the ContainerBuilderAutofac - 带有 OWIN 的 SignalR.获取对 ContainerBuilder 的引用
【发布时间】:2015-01-21 10:16:15
【问题描述】:

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

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

这会产生以下类:

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 代码从 global.asax 上的 application_start 运行,同时 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" />

【问题讨论】:

    标签: c# asp.net-mvc-4 signalr autofac


    【解决方案1】:

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

    如果您使用 OWIN 托管您的应用程序,我建议您将整个启动切换到 OWIN(至少是启动逻辑),这样您就不必尝试同步对容器的访问或传递东西。如果您愿意,您仍然可以在 Global.asax 中保留其他事件处理程序(Application_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 中间件。然后,您可以传递容器以在各个应用程序类型设置中使用(就像您在 SignalR 中看到的那样)。

    然后用主启动类引导整个事情:

    [assembly: OwinStartup(typeof(Startup))]
    

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

    【讨论】:

    • 感谢您的详细回答。我将按照您的建议重组我的启动代码。
    猜你喜欢
    • 2015-06-29
    • 2019-02-09
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 1970-01-01
    相关资源
    最近更新 更多