Autofac - SignalR与OWIN。获得参考ContainerBuilder [英] Autofac - SignalR with OWIN. getting reference to the ContainerBuilder

查看:966
本文介绍了Autofac - SignalR与OWIN。获得参考ContainerBuilder的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Autofac和我有有autofac模块在其他组件。如果没有SignalR / autofac整合,我的应用程序完美的作品,据国际奥委会关注现有的MVC应用4。我在SignalR中心这我试图把依赖注入通过构造补充说。我按照文档和实施的code的例子。

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

这将导致这个下面的类:

 公共类SignalRConfig
{
    公共无效配置(IAppBuilder应用程序)
    {
        VAR建设者=新ContainerBuilder();
        无功配置=新HubConfiguration();        大会thisAssembly = typeof运算(SignalRConfig).Assembly;        builder.RegisterHubs(thisAssembly);        变种容器= builder.Build();
        config.Resolver =新AutofacDependencyResolver(容器);
        app.UseAutofacMiddleware(容器);
        app.MapSignalR(/ signalr,配置);
    }
}

这是迷上了这条线将被添加到我的AssemblyInfo.cs

  [汇编:OwinStartup(typeof运算(SignalRConfig))]

但在运行时它不工作作为我的集线器没有参数的构造函数,它不能解析的依赖。我的假设是,我创建一个新的ContainerBuilder(按文档),而且这种情况下没有什么上注册。其实我是想提及,这是围绕我的模块,知道我所有的注册的类型通过ContainerBuilder。我只是不知道如何做到这一点。现有的国际奥委会code从在Global.asax中的Application_Start运行和SignalRConfig运行在同一时间。我不想持有ContainerBuilder在一个单身的感觉很脏,但我不能找到任何其他解决方案。

下面是我的NuGet包配置的部分显示的版本号等。

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


解决方案

听起来你是混合遗产如IIS托管机制(的Application_Start )的新OWIN托管( OwinStartup ),而这将是很难纠正。

如果您正在使用OWIN托管的应用程序,我建议交换了整个启动时OWIN(至少启动逻辑),所以你不必尝试同步进入容器或通过周围的事物。您仍然可以保留其他事件处理程序(的Application_Error 等等)在Global.asax中,如果你喜欢,只要统一启动逻辑在OWIN启动类。

您仍然可以让事情还算整洁通过分离层成被调用不同的启动类。

 公共静态类启动
{
  公共静态无效配置(IAppBuilder应用程序)
  {
    变种容器= DependencyConfiguration.Configure(应用程序);
    SignalRConfiguration.Configure(应用程序容器);
    MvcConfiguration.Configure(应用程序容器);
  }
}公共静态类DependencyConfiguration
{
  公共静态配置的IContainer(IAppBuilder应用程序)
  {
    VAR建设者=新ContainerBuilder();
    builder.RegisterHubs(typeof运算(SignalRConfiguration).Assembly);
    变种容器= builder.Build();
    app.UseAutofacMiddleware(容器);
    返回容器中;
  }
}公共静态类SignalRConfiguration
{
  公共静态无效配置(IAppBuilder应用,集装箱的IContainer)
  {
    无功配置=新HubConfiguration();
    config.Resolver =新AutofacDependencyResolver(容器);
    app.MapSignalR(/ signalr,配置);
  }
}

...等等。最重要的一点是,你已经得到了所有已注册的依赖一次和Autofac中间件先加入。然后,您可以通过各地的个人应用程序类型设置使用(像你SignalR看到有)的容器。

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

  [汇编:OwinStartup(typeof运算(启动))]

有一个很大的好处这一点。你避开你正在运行进入比赛状态;你并不需要去尝试并同步或重新排序的东西;和你有很多的控制。如果你想将它还设置您在ASP.NET vNext一个更好的地方,因为一切的OWIN即可。

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. I have added in SignalR hubs which I am trying to inject dependencies into via the constructor. I have followed the documentation and implemented the code example from.

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

[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. I actually want the reference to the ContainerBuilder that is passed around my modules that knows about all my registered types. 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. I dont want to hold the ContainerBuilder in a singleton as it feels dirty but I cant find any other solution.

Here is a section of my nuget package config showing the version numbers etc

  <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.

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. 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.

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. You can then pass the container around to be used in individual application type setups (like you see there with 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.

这篇关于Autofac - SignalR与OWIN。获得参考ContainerBuilder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆