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。
我有一个使用 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。