简体   繁体   English

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

[英]Autofac - SignalR with OWIN. getting reference to the ContainerBuilder

I have an existing MVC 4 application that uses Autofac and I have other assemblies that have autofac Modules in. Without SignalR/autofac integration, my application works perfectly as far as IOC is concerned. 我有一个使用Autofac的现有MVC 4应用程序,还有其他装有autofac模块的程序集。没有SignalR / autofac集成,就IOC而言,我的应用程序可以完美运行。 I have added in SignalR hubs which I am trying to inject dependencies into via the constructor. 我已经添加了SignalR集线器,试图通过构造函数将依赖项注入其中。 I have followed the documentation and implemented the code example from. 我遵循了文档并从中实现了代码示例。

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

Which results in this following 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);
    }
}

This is hooked up with this line which is added to my AssemblyInfo.cs 这与添加到我的AssemblyInfo.cs中的这一行挂钩

[assembly: OwinStartup(typeof(SignalRConfig))]

But its not working at runtime as my hub does not have a parameterless constructor and it cannot resolve the dependency. 但是它在运行时不起作用,因为我的集线器没有无参数构造函数,并且无法解析依赖关系。 My assumption is that I am creating a new ContainerBuilder (as per docs) and that this instance has nothing registered on it. 我的假设是我正在创建一个新的ContainerBuilder(根据docs),并且此实例上没有任何注册。 I actually want the reference to the ContainerBuilder that is passed around my modules that knows about all my registered types. 我实际上想要引用关于我知道所有注册类型的模块的ContainerBuilder。 I just dont know how to do it. 我只是不知道该怎么做。 The existing IOC code runs from the application_start on the global.asax and the SignalRConfig runs at the same time. 现有的IOC代码从global.asax上的application_start运行,而SignalRConfig同时运行。 I dont want to hold the ContainerBuilder in a singleton as it feels dirty but I cant find any other solution. 我不想将ContainerBuilder放在一个盒子里,因为它感觉很脏,但是我找不到其他解决方案。

Here is a section of my nuget package config showing the version numbers etc 这是我的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" />

It sounds like you're mixing legacy IIS hosting mechanisms ( Application_Start ) with new OWIN hosting ( OwinStartup ) and that's going to be hard to rectify. 听起来您正在将旧的IIS托管机制( Application_Start )与新的OWIN托管( OwinStartup )混合OwinStartup ,这将很难纠正。

If you're hosting your app using OWIN, I'd recommend switching the whole startup to OWIN (at least the startup logic) so you don't have to try to synchronize access to the container or pass things around. 如果您使用OWIN托管应用程序,建议您将整个启动过程切换到OWIN(至少是启动逻辑),这样就不必尝试同步对容器的访问或传递信息。 You can still keep other event handlers ( Application_Error and such) in Global.asax if you like, just unify the startup logic in your OWIN startup class. 如果愿意,您仍然可以在Global.asax中保留其他事件处理程序( Application_Error等),只需在OWIN启动类中统一启动逻辑即可。

You can still keep things fairly tidy by separating "layers" into different startup classes that get called. 您仍然可以通过将“层”分成不同的被调用的启动类来保持整洁。

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);
  }
}

...and so on. ...等等。 The important bit is that you've got all the dependencies registered at once and the Autofac middleware is added first. 重要的一点是您一次注册了所有依赖项,并且首先添加了Autofac中间件。 You can then pass the container around to be used in individual application type setups (like you see there with SignalR). 然后,您可以传递该容器以用于各个应用程序类型设置(如在SignalR上看到的那样)。

Then bootstrap the whole thing with the main startup class: 然后使用主启动类引导整个过程:

[assembly: OwinStartup(typeof(Startup))]

There's a lot of benefit to this. 这有很多好处。 You sidestep the race condition you're running into; 您回避了正在遇到的比赛条件; you don't need to try and synchronize or reorder things; 您无需尝试对事物进行同步或重新排序; and you have a lot of control. 而且您拥有很多控制权。 It also sets you up in a better place for ASP.NET vNext if you want to port, since everything's OWIN then. 如果要移植,它也为ASP.NET vNext设置了更好的位置,因为那时一切都是OWIN。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM